summaryrefslogtreecommitdiffstats
path: root/document
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2018-06-14 09:37:36 +0200
committerGitHub <noreply@github.com>2018-06-14 09:37:36 +0200
commit3302fb4a790925ad0437d2bd7b4747c4d02a971b (patch)
treeb4299bc5f651565a86180d0389eef9df4bbdbbbc /document
parentf562d35d3636cfbb6fd6d9caeb94d97dcdfc0f8e (diff)
parent747bda75a444c866d8e4752315e6949fd23194bd (diff)
Merge pull request #6185 from vespa-engine/balder/balder/prepare-lazy-deserialize-rebased-2
Balder/balder/prepare lazy deserialize rebased 2
Diffstat (limited to 'document')
-rw-r--r--document/src/tests/documentselectparsertest.cpp3
-rw-r--r--document/src/tests/documentupdatetestcase.cpp275
-rw-r--r--document/src/tests/fieldpathupdatetestcase.cpp82
-rw-r--r--document/src/tests/testxml.cpp2
-rw-r--r--document/src/vespa/document/base/forcelink.cpp2
-rw-r--r--document/src/vespa/document/serialization/vespadocumentserializer.cpp14
-rw-r--r--document/src/vespa/document/update/documentupdate.cpp298
-rw-r--r--document/src/vespa/document/update/documentupdate.h75
8 files changed, 399 insertions, 352 deletions
diff --git a/document/src/tests/documentselectparsertest.cpp b/document/src/tests/documentselectparsertest.cpp
index 05ec2ce99d0..2433bfecdab 100644
--- a/document/src/tests/documentselectparsertest.cpp
+++ b/document/src/tests/documentselectparsertest.cpp
@@ -163,8 +163,7 @@ DocumentUpdate::SP DocumentSelectParserTest::createUpdate(
const std::string& hstr)
{
const DocumentType* type = _repo->getDocumentType(doctype);
- DocumentUpdate::SP doc(
- new DocumentUpdate(*type, DocumentId(id)));
+ DocumentUpdate::SP doc(new DocumentUpdate(*_repo, *type, DocumentId(id)));
doc->addUpdate(FieldUpdate(doc->getType().getField("headerval"))
.addUpdate(AssignValueUpdate(IntFieldValue(hint))));
doc->addUpdate(FieldUpdate(doc->getType().getField("hstringval"))
diff --git a/document/src/tests/documentupdatetestcase.cpp b/document/src/tests/documentupdatetestcase.cpp
index 9ba17d95264..2a77d610420 100644
--- a/document/src/tests/documentupdatetestcase.cpp
+++ b/document/src/tests/documentupdatetestcase.cpp
@@ -191,16 +191,15 @@ DocumentUpdateTest::testSimpleUsage() {
fieldUpdate.addUpdate(AssignValueUpdate(IntFieldValue(1)));
ByteBuffer::UP fieldBuf = serialize(fieldUpdate);
fieldBuf->flip();
- FieldUpdate fieldUpdateCopy(repo, *docType, *fieldBuf,
- Document::getNewestSerializationVersion());
+ FieldUpdate fieldUpdateCopy(repo, *docType, *fieldBuf, Document::getNewestSerializationVersion());
CPPUNIT_ASSERT_EQUAL(fieldUpdate, fieldUpdateCopy);
// Test that a document update can be serialized
- DocumentUpdate docUpdate(*docType, DocumentId("doc::testdoc"));
+ DocumentUpdate docUpdate(repo, *docType, DocumentId("doc::testdoc"));
docUpdate.addUpdate(fieldUpdateCopy);
- ByteBuffer::UP docBuf = serialize42(docUpdate);
+ ByteBuffer::UP docBuf = serializeHEAD(docUpdate);
docBuf->flip();
- DocumentUpdate::UP docUpdateCopy(DocumentUpdate::create42(repo, *docBuf));
+ auto docUpdateCopy(DocumentUpdate::createHEAD(repo, nbostream(docBuf->getBufferAtPos(), docBuf->getRemaining())));
// Create a test document
Document doc(*docType, DocumentId("doc::testdoc"));
@@ -214,62 +213,53 @@ DocumentUpdateTest::testSimpleUsage() {
// Verify that we can apply simple updates to it
{
Document updated(doc);
- DocumentUpdate upd(*docType, DocumentId("doc::testdoc"));
- upd.addUpdate(FieldUpdate(docType->getField("intf"))
- .addUpdate(ClearValueUpdate()));
+ DocumentUpdate upd(repo, *docType, DocumentId("doc::testdoc"));
+ upd.addUpdate(FieldUpdate(docType->getField("intf")).addUpdate(ClearValueUpdate()));
upd.applyTo(updated);
CPPUNIT_ASSERT(doc != updated);
CPPUNIT_ASSERT(! updated.getValue("intf"));
}
{
Document updated(doc);
- DocumentUpdate upd(*docType, DocumentId("doc::testdoc"));
- upd.addUpdate(FieldUpdate(docType->getField("intf"))
- .addUpdate(AssignValueUpdate(IntFieldValue(15))));
+ DocumentUpdate upd(repo, *docType, DocumentId("doc::testdoc"));
+ upd.addUpdate(FieldUpdate(docType->getField("intf")).addUpdate(AssignValueUpdate(IntFieldValue(15))));
upd.applyTo(updated);
CPPUNIT_ASSERT(doc != updated);
CPPUNIT_ASSERT_EQUAL(15, updated.getValue("intf")->getAsInt());
}
{
Document updated(doc);
- DocumentUpdate upd(*docType, DocumentId("doc::testdoc"));
- upd.addUpdate(FieldUpdate(docType->getField("intf"))
- .addUpdate(ArithmeticValueUpdate(
- ArithmeticValueUpdate::Add, 15)));
+ DocumentUpdate upd(repo, *docType, DocumentId("doc::testdoc"));
+ upd.addUpdate(FieldUpdate(docType->getField("intf")).addUpdate(ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 15)));
upd.applyTo(updated);
CPPUNIT_ASSERT(doc != updated);
CPPUNIT_ASSERT_EQUAL(20, updated.getValue("intf")->getAsInt());
}
{
Document updated(doc);
- DocumentUpdate upd(*docType, DocumentId("doc::testdoc"));
- upd.addUpdate(FieldUpdate(docType->getField("intarr"))
- .addUpdate(AddValueUpdate(IntFieldValue(4))));
+ DocumentUpdate upd(repo, *docType, DocumentId("doc::testdoc"));
+ upd.addUpdate(FieldUpdate(docType->getField("intarr")).addUpdate(AddValueUpdate(IntFieldValue(4))));
upd.applyTo(updated);
CPPUNIT_ASSERT(doc != updated);
- std::unique_ptr<ArrayFieldValue> val(dynamic_cast<ArrayFieldValue*>(
- updated.getValue("intarr").release()));
+ std::unique_ptr<ArrayFieldValue> val(dynamic_cast<ArrayFieldValue*>(updated.getValue("intarr").release()));
CPPUNIT_ASSERT_EQUAL(size_t(3), val->size());
CPPUNIT_ASSERT_EQUAL(4, (*val)[2].getAsInt());
}
{
Document updated(doc);
- DocumentUpdate upd(*docType, DocumentId("doc::testdoc"));
- upd.addUpdate(FieldUpdate(docType->getField("intarr"))
- .addUpdate(RemoveValueUpdate(IntFieldValue(3))));
+ DocumentUpdate upd(repo, *docType, DocumentId("doc::testdoc"));
+ upd.addUpdate(FieldUpdate(docType->getField("intarr")).addUpdate(RemoveValueUpdate(IntFieldValue(3))));
upd.applyTo(updated);
CPPUNIT_ASSERT(doc != updated);
- std::unique_ptr<ArrayFieldValue> val(dynamic_cast<ArrayFieldValue*>(
- updated.getValue("intarr").release()));
+ std::unique_ptr<ArrayFieldValue> val(dynamic_cast<ArrayFieldValue*>(updated.getValue("intarr").release()));
CPPUNIT_ASSERT_EQUAL(size_t(1), val->size());
CPPUNIT_ASSERT_EQUAL(7, (*val)[0].getAsInt());
}
{
Document updated(doc);
- DocumentUpdate upd(*docType, DocumentId("doc::testdoc"));
+ DocumentUpdate upd(repo, *docType, DocumentId("doc::testdoc"));
upd.addUpdate(FieldUpdate(docType->getField("bytef"))
- .addUpdate(ArithmeticValueUpdate(
- ArithmeticValueUpdate::Add, 15)));
+ .addUpdate(ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 15)));
upd.applyTo(updated);
CPPUNIT_ASSERT(doc != updated);
CPPUNIT_ASSERT_EQUAL(15, (int) updated.getValue("bytef")->getAsByte());
@@ -286,9 +276,8 @@ DocumentUpdateTest::testClearField()
CPPUNIT_ASSERT_EQUAL(4, doc->getValue("headerval")->getAsInt());
// Apply an update.
- DocumentUpdate(*doc->getDataType(), doc->getId())
- .addUpdate(FieldUpdate(doc->getField("headerval"))
- .addUpdate(AssignValueUpdate()))
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
+ .addUpdate(FieldUpdate(doc->getField("headerval")).addUpdate(AssignValueUpdate()))
.applyTo(*doc);
CPPUNIT_ASSERT(!doc->getValue("headerval"));
}
@@ -303,9 +292,8 @@ DocumentUpdateTest::testUpdateApplySingleValue()
CPPUNIT_ASSERT_EQUAL(4, doc->getValue("headerval")->getAsInt());
// Apply an update.
- DocumentUpdate(*doc->getDataType(), doc->getId())
- .addUpdate(FieldUpdate(doc->getField("headerval"))
- .addUpdate(AssignValueUpdate(IntFieldValue(9))))
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
+ .addUpdate(FieldUpdate(doc->getField("headerval")).addUpdate(AssignValueUpdate(IntFieldValue(9))))
.applyTo(*doc);
CPPUNIT_ASSERT_EQUAL(9, doc->getValue("headerval")->getAsInt());
}
@@ -316,28 +304,23 @@ DocumentUpdateTest::testUpdateArray()
// Create a document.
TestDocMan docMan;
Document::UP doc(docMan.createDocument());
- CPPUNIT_ASSERT_EQUAL((document::FieldValue*)NULL,
- doc->getValue(doc->getField("tags")).get());
+ CPPUNIT_ASSERT_EQUAL((document::FieldValue*)NULL, doc->getValue(doc->getField("tags")).get());
// Assign array field.
ArrayFieldValue myarray(doc->getType().getField("tags").getDataType());
myarray.add(StringFieldValue("foo"));
myarray.add(StringFieldValue("bar"));
- DocumentUpdate(*doc->getDataType(), doc->getId())
- .addUpdate(FieldUpdate(doc->getField("tags"))
- .addUpdate(AssignValueUpdate(myarray)))
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
+ .addUpdate(FieldUpdate(doc->getField("tags")).addUpdate(AssignValueUpdate(myarray)))
.applyTo(*doc);
- std::unique_ptr<ArrayFieldValue>
- fval1(doc->getAs<ArrayFieldValue>(doc->getField("tags")));
+ auto fval1(doc->getAs<ArrayFieldValue>(doc->getField("tags")));
CPPUNIT_ASSERT_EQUAL((size_t) 2, fval1->size());
- CPPUNIT_ASSERT_EQUAL(std::string("foo"),
- std::string((*fval1)[0].getAsString()));
- CPPUNIT_ASSERT_EQUAL(std::string("bar"),
- std::string((*fval1)[1].getAsString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("foo"), std::string((*fval1)[0].getAsString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("bar"), std::string((*fval1)[1].getAsString()));
// Append array field
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(doc->getField("tags"))
.addUpdate(AddValueUpdate(StringFieldValue("another")))
.addUpdate(AddValueUpdate(StringFieldValue("tag"))))
@@ -345,21 +328,16 @@ DocumentUpdateTest::testUpdateArray()
std::unique_ptr<ArrayFieldValue>
fval2(doc->getAs<ArrayFieldValue>(doc->getField("tags")));
CPPUNIT_ASSERT_EQUAL((size_t) 4, fval2->size());
- CPPUNIT_ASSERT_EQUAL(std::string("foo"),
- std::string((*fval2)[0].getAsString()));
- CPPUNIT_ASSERT_EQUAL(std::string("bar"),
- std::string((*fval2)[1].getAsString()));
- CPPUNIT_ASSERT_EQUAL(std::string("another"),
- std::string((*fval2)[2].getAsString()));
- CPPUNIT_ASSERT_EQUAL(std::string("tag"),
- std::string((*fval2)[3].getAsString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("foo"), std::string((*fval2)[0].getAsString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("bar"), std::string((*fval2)[1].getAsString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("another"), std::string((*fval2)[2].getAsString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("tag"), std::string((*fval2)[3].getAsString()));
// Append single value.
try {
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(doc->getField("tags"))
- .addUpdate(AssignValueUpdate(
- StringFieldValue("THROW MEH!"))))
+ .addUpdate(AssignValueUpdate(StringFieldValue("THROW MEH!"))))
.applyTo(*doc);
CPPUNIT_FAIL("Expected exception when assinging a string value to an "
"array field.");
@@ -369,25 +347,22 @@ DocumentUpdateTest::testUpdateArray()
}
// Remove array field.
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(doc->getField("tags"))
.addUpdate(RemoveValueUpdate(StringFieldValue("foo")))
.addUpdate(RemoveValueUpdate(StringFieldValue("tag"))))
.applyTo(*doc);
- std::unique_ptr<ArrayFieldValue>
- fval3(doc->getAs<ArrayFieldValue>(doc->getField("tags")));
+ auto fval3(doc->getAs<ArrayFieldValue>(doc->getField("tags")));
CPPUNIT_ASSERT_EQUAL((size_t) 2, fval3->size());
- CPPUNIT_ASSERT_EQUAL(std::string("bar"),
- std::string((*fval3)[0].getAsString()));
- CPPUNIT_ASSERT_EQUAL(std::string("another"),
- std::string((*fval3)[1].getAsString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("bar"), std::string((*fval3)[0].getAsString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("another"), std::string((*fval3)[1].getAsString()));
// Remove array from array.
ArrayFieldValue myarray2(doc->getType().getField("tags").getDataType());
myarray2.add(StringFieldValue("foo"));
myarray2.add(StringFieldValue("bar"));
try {
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(doc->getField("tags"))
.addUpdate(RemoveValueUpdate(myarray2)))
.applyTo(*doc);
@@ -412,12 +387,10 @@ DocumentUpdateTest::testUpdateWeightedSet()
WeightedSetFieldValue wset(field.getDataType());
wset.add(StringFieldValue("foo"), 3);
wset.add(StringFieldValue("bar"), 14);
- DocumentUpdate(*doc->getDataType(), doc->getId())
- .addUpdate(FieldUpdate(field)
- .addUpdate(AssignValueUpdate(wset)))
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
+ .addUpdate(FieldUpdate(field).addUpdate(AssignValueUpdate(wset)))
.applyTo(*doc);
- std::unique_ptr<WeightedSetFieldValue>
- fval1(doc->getAs<WeightedSetFieldValue>(field));
+ auto fval1(doc->getAs<WeightedSetFieldValue>(field));
CPPUNIT_ASSERT_EQUAL((size_t) 2, fval1->size());
CPPUNIT_ASSERT(fval1->contains(StringFieldValue("foo")));
CPPUNIT_ASSERT(fval1->find(StringFieldValue("foo")) != fval1->end());
@@ -430,12 +403,11 @@ DocumentUpdateTest::testUpdateWeightedSet()
WeightedSetFieldValue wset2(field.getDataType());
wset2.add(StringFieldValue("foo"), 16);
wset2.add(StringFieldValue("bar"), 24);
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(field)
.addUpdate(AssignValueUpdate(wset2)))
.applyTo(*doc);
- std::unique_ptr<WeightedSetFieldValue>
- fval2(doc->getAs<WeightedSetFieldValue>(field));
+ auto fval2(doc->getAs<WeightedSetFieldValue>(field));
CPPUNIT_ASSERT_EQUAL((size_t) 2, fval2->size());
CPPUNIT_ASSERT(fval2->contains(StringFieldValue("foo")));
CPPUNIT_ASSERT(fval2->find(StringFieldValue("foo")) != fval1->end());
@@ -445,12 +417,10 @@ DocumentUpdateTest::testUpdateWeightedSet()
CPPUNIT_ASSERT_EQUAL(24, fval2->get(StringFieldValue("bar"), 0));
// Append weighted field
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(field)
- .addUpdate(AddValueUpdate(StringFieldValue("foo"))
- .setWeight(3))
- .addUpdate(AddValueUpdate(StringFieldValue("too"))
- .setWeight(14)))
+ .addUpdate(AddValueUpdate(StringFieldValue("foo")).setWeight(3))
+ .addUpdate(AddValueUpdate(StringFieldValue("too")).setWeight(14)))
.applyTo(*doc);
std::unique_ptr<WeightedSetFieldValue>
fval3(doc->getAs<WeightedSetFieldValue>(field));
@@ -463,13 +433,12 @@ DocumentUpdateTest::testUpdateWeightedSet()
CPPUNIT_ASSERT_EQUAL(14, fval3->get(StringFieldValue("too"), 0));
// Remove weighted field
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(field)
.addUpdate(RemoveValueUpdate(StringFieldValue("foo")))
.addUpdate(RemoveValueUpdate(StringFieldValue("too"))))
.applyTo(*doc);
- std::unique_ptr<WeightedSetFieldValue>
- fval4(doc->getAs<WeightedSetFieldValue>(field));
+ auto fval4(doc->getAs<WeightedSetFieldValue>(field));
CPPUNIT_ASSERT_EQUAL((size_t) 1, fval4->size());
CPPUNIT_ASSERT(!fval4->contains(StringFieldValue("foo")));
CPPUNIT_ASSERT(fval4->contains(StringFieldValue("bar")));
@@ -500,21 +469,18 @@ struct WeightedSetAutoCreateFixture
// and remove-if-zero attributes set. Attempting to explicitly create
// a field matching those characteristics will in fact fail with a
// redefinition error.
- builder.document(42, "test",
- Struct("test.header")
- .addField("strwset", DataType::T_TAG),
- Struct("test.body"));
+ builder.document(42, "test", Struct("test.header").addField("strwset", DataType::T_TAG), Struct("test.body"));
return builder.config();
}
};
-WeightedSetAutoCreateFixture::~WeightedSetAutoCreateFixture() {}
+WeightedSetAutoCreateFixture::~WeightedSetAutoCreateFixture() = default;
WeightedSetAutoCreateFixture::WeightedSetAutoCreateFixture()
: repo(makeConfig()),
docType(repo.getDocumentType("test")),
doc(*docType, DocumentId("doc::testdoc")),
field(docType->getField("strwset")),
- update(*docType, DocumentId("doc::testdoc"))
+ update(repo, *docType, DocumentId("doc::testdoc"))
{
update.addUpdate(FieldUpdate(field)
.addUpdate(MapValueUpdate(StringFieldValue("foo"),
@@ -585,7 +551,8 @@ void DocumentUpdateTest::testReadSerializedFile()
}
close(fd);
- DocumentUpdate::UP updp(DocumentUpdate::create42(repo, buf));
+ nbostream is(buf.getBufferAtPos(), buf.getRemaining());
+ DocumentUpdate::UP updp(DocumentUpdate::create42(repo, is));
DocumentUpdate& upd(*updp);
const DocumentType *type = repo.getDocumentType("serializetest");
@@ -647,7 +614,7 @@ void DocumentUpdateTest::testGenerateSerializedFile()
DocumentTypeRepo repo(readDocumenttypesConfig(file_name));
const DocumentType *type(repo.getDocumentType("serializetest"));
- DocumentUpdate upd(*type, DocumentId(DocIdString("update", "test")));
+ DocumentUpdate upd(repo, *type, DocumentId(DocIdString("update", "test")));
upd.addUpdate(FieldUpdate(type->getField("intfield"))
.addUpdate(AssignValueUpdate(IntFieldValue(4))));
upd.addUpdate(FieldUpdate(type->getField("floatfield"))
@@ -678,11 +645,10 @@ void DocumentUpdateTest::testSetBadFieldTypes()
// Create a test document
TestDocMan docMan;
Document::UP doc(docMan.createDocument());
- CPPUNIT_ASSERT_EQUAL((document::FieldValue*)NULL,
- doc->getValue(doc->getField("headerval")).get());
+ CPPUNIT_ASSERT_EQUAL((document::FieldValue*)NULL, doc->getValue(doc->getField("headerval")).get());
// Assign a float value to an int field.
- DocumentUpdate update(*doc->getDataType(), doc->getId());
+ DocumentUpdate update(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
try {
update.addUpdate(FieldUpdate(doc->getField("headerval"))
.addUpdate(AssignValueUpdate(FloatFieldValue(4.00f))));
@@ -701,23 +667,19 @@ void DocumentUpdateTest::testSetBadFieldTypes()
void
DocumentUpdateTest::testUpdateApplyNoParams()
{
- // Create a test document
TestDocMan docMan;
Document::UP doc(docMan.createDocument());
- CPPUNIT_ASSERT_EQUAL((document::FieldValue*)NULL,
- doc->getValue(doc->getField("tags")).get());
+ CPPUNIT_ASSERT_EQUAL((document::FieldValue*)NULL, doc->getValue(doc->getField("tags")).get());
// Assign array field with no parameters - illegal.
- DocumentUpdate update(*doc->getDataType(), doc->getId());
+ DocumentUpdate update(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
try {
- update.addUpdate(FieldUpdate(doc->getField("tags"))
- .addUpdate(AssignValueUpdate()));
+ update.addUpdate(FieldUpdate(doc->getField("tags")).addUpdate(AssignValueUpdate()));
CPPUNIT_FAIL("Expected exception when assign a NULL value.");
} catch (std::exception& e) {
; // fprintf(stderr, "Got exception => OK: %s\n", e.what());
}
- // Apply update
update.applyTo(*doc);
// Verify that the field was cleared in the document.
@@ -727,20 +689,16 @@ DocumentUpdateTest::testUpdateApplyNoParams()
void
DocumentUpdateTest::testUpdateApplyNoArrayValues()
{
- // Create a test document
TestDocMan docMan;
Document::UP doc(docMan.createDocument());
const Field &field(doc->getType().getField("tags"));
- CPPUNIT_ASSERT_EQUAL((document::FieldValue*) 0,
- doc->getValue(field).get());
+ CPPUNIT_ASSERT_EQUAL((document::FieldValue*) 0, doc->getValue(field).get());
// Assign array field with no array values = empty array
- DocumentUpdate update(*doc->getDataType(), doc->getId());
+ DocumentUpdate update(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
update.addUpdate(FieldUpdate(field)
- .addUpdate(AssignValueUpdate(
- ArrayFieldValue(field.getDataType()))));
+ .addUpdate(AssignValueUpdate(ArrayFieldValue(field.getDataType()))));
- // Apply update
update.applyTo(*doc);
// Verify that the field was set in the document
@@ -759,7 +717,7 @@ DocumentUpdateTest::testUpdateArrayEmptyParamValue()
CPPUNIT_ASSERT_EQUAL((document::FieldValue*) 0, doc->getValue(field).get());
// Assign array field with no array values = empty array.
- DocumentUpdate update(*doc->getDataType(), doc->getId());
+ DocumentUpdate update(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
update.addUpdate(FieldUpdate(field).addUpdate(AssignValueUpdate(ArrayFieldValue(field.getDataType()))));
update.applyTo(*doc);
@@ -769,7 +727,7 @@ DocumentUpdateTest::testUpdateArrayEmptyParamValue()
CPPUNIT_ASSERT_EQUAL((size_t) 0, fval1->size());
// Remove array field.
- DocumentUpdate update2(*doc->getDataType(), doc->getId());
+ DocumentUpdate update2(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
update2.addUpdate(FieldUpdate(field).addUpdate(ClearValueUpdate()));
update2.applyTo(*doc);
@@ -788,7 +746,7 @@ DocumentUpdateTest::testUpdateWeightedSetEmptyParamValue()
CPPUNIT_ASSERT_EQUAL((document::FieldValue*) 0, doc->getValue(field).get());
// Assign weighted set with no items = empty set.
- DocumentUpdate update(*doc->getDataType(), doc->getId());
+ DocumentUpdate update(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
update.addUpdate(FieldUpdate(field).addUpdate(AssignValueUpdate(WeightedSetFieldValue(field.getDataType()))));
update.applyTo(*doc);
@@ -798,7 +756,7 @@ DocumentUpdateTest::testUpdateWeightedSetEmptyParamValue()
CPPUNIT_ASSERT_EQUAL((size_t) 0, fval1->size());
// Remove weighted set field.
- DocumentUpdate update2(*doc->getDataType(), doc->getId());
+ DocumentUpdate update2(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
update2.addUpdate(FieldUpdate(field).addUpdate(ClearValueUpdate()));
update2.applyTo(*doc);
@@ -817,7 +775,7 @@ DocumentUpdateTest::testUpdateArrayWrongSubtype()
CPPUNIT_ASSERT_EQUAL((document::FieldValue*) 0, doc->getValue(field).get());
// Assign int values to string array.
- DocumentUpdate update(*doc->getDataType(), doc->getId());
+ DocumentUpdate update(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
try {
update.addUpdate(FieldUpdate(field)
.addUpdate(AddValueUpdate(IntFieldValue(123)))
@@ -842,17 +800,14 @@ DocumentUpdateTest::testUpdateWeightedSetWrongSubtype()
TestDocMan docMan;
Document::UP doc(docMan.createDocument());
const Field &field(doc->getType().getField("stringweightedset"));
- CPPUNIT_ASSERT_EQUAL((document::FieldValue*) 0,
- doc->getValue(field).get());
+ CPPUNIT_ASSERT_EQUAL((document::FieldValue*) 0, doc->getValue(field).get());
// Assign int values to string array.
- DocumentUpdate update(*doc->getDataType(), doc->getId());
+ DocumentUpdate update(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
try {
update.addUpdate(FieldUpdate(field)
- .addUpdate(AddValueUpdate(IntFieldValue(123))
- .setWeight(1000))
- .addUpdate(AddValueUpdate(IntFieldValue(456))
- .setWeight(2000)));
+ .addUpdate(AddValueUpdate(IntFieldValue(123)).setWeight(1000))
+ .addUpdate(AddValueUpdate(IntFieldValue(456)).setWeight(2000)));
CPPUNIT_FAIL("Expected exception when adding wrong type.");
} catch (std::exception& e) {
; // fprintf(stderr, "Got exception => OK: %s\n", e.what());
@@ -879,79 +834,61 @@ DocumentUpdateTest::testMapValueUpdate()
doc->setValue(field1, wsval1);
doc->setValue(field2, wsval2);
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(field1)
- .addUpdate(MapValueUpdate(
- StringFieldValue("banana"),
- ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 1.0)
- )))
+ .addUpdate(MapValueUpdate(StringFieldValue("banana"),
+ ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 1.0))))
.applyTo(*doc);
std::unique_ptr<WeightedSetFieldValue> fv1 =
doc->getAs<WeightedSetFieldValue>(field1);
CPPUNIT_ASSERT(fv1->size() == 0);
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(field2)
- .addUpdate(MapValueUpdate(
- StringFieldValue("banana"),
- ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 1.0)
- )))
+ .addUpdate(MapValueUpdate(StringFieldValue("banana"),
+ ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 1.0))))
.applyTo(*doc);
- std::unique_ptr<WeightedSetFieldValue> fv2 =
- doc->getAs<WeightedSetFieldValue>(field2);
+ auto fv2 = doc->getAs<WeightedSetFieldValue>(field2);
CPPUNIT_ASSERT(fv2->size() == 1);
CPPUNIT_ASSERT(fv1->find(StringFieldValue("apple")) == fv1->end());
- DocumentUpdate(*doc->getDataType(), doc->getId())
- .addUpdate(FieldUpdate(field1)
- .addUpdate(ClearValueUpdate()))
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
+ .addUpdate(FieldUpdate(field1).addUpdate(ClearValueUpdate()))
.applyTo(*doc);
- DocumentUpdate(*doc->getDataType(), doc->getId())
- .addUpdate(FieldUpdate(field1)
- .addUpdate(AddValueUpdate(StringFieldValue("apple"))
- .setWeight(1)))
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
+ .addUpdate(FieldUpdate(field1).addUpdate(AddValueUpdate(StringFieldValue("apple")).setWeight(1)))
.applyTo(*doc);
- std::unique_ptr<WeightedSetFieldValue>
- fval3(doc->getAs<WeightedSetFieldValue>(field1));
+ auto fval3(doc->getAs<WeightedSetFieldValue>(field1));
CPPUNIT_ASSERT(fval3->find(StringFieldValue("apple")) != fval3->end());
CPPUNIT_ASSERT_EQUAL(1, fval3->get(StringFieldValue("apple")));
- DocumentUpdate(*doc->getDataType(), doc->getId())
- .addUpdate(FieldUpdate(field2)
- .addUpdate(AddValueUpdate(StringFieldValue("apple"))
- .setWeight(1)))
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
+ .addUpdate(FieldUpdate(field2).addUpdate(AddValueUpdate(StringFieldValue("apple")).setWeight(1)))
.applyTo(*doc);
- std::unique_ptr<WeightedSetFieldValue>
- fval3b(doc->getAs<WeightedSetFieldValue>(field2));
+ auto fval3b(doc->getAs<WeightedSetFieldValue>(field2));
CPPUNIT_ASSERT(fval3b->find(StringFieldValue("apple")) != fval3b->end());
CPPUNIT_ASSERT_EQUAL(1, fval3b->get(StringFieldValue("apple")));
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(field1)
- .addUpdate(MapValueUpdate(
- StringFieldValue("apple"),
- ArithmeticValueUpdate(ArithmeticValueUpdate::Sub, 1.0)
- )))
+ .addUpdate(MapValueUpdate(StringFieldValue("apple"),
+ ArithmeticValueUpdate(ArithmeticValueUpdate::Sub, 1.0))))
.applyTo(*doc);
- std::unique_ptr<WeightedSetFieldValue> fv3 =
- doc->getAs<WeightedSetFieldValue>(field1);
+ auto fv3 = doc->getAs<WeightedSetFieldValue>(field1);
CPPUNIT_ASSERT(fv3->find(StringFieldValue("apple")) != fv3->end());
CPPUNIT_ASSERT_EQUAL(0, fv3->get(StringFieldValue("apple")));
- DocumentUpdate(*doc->getDataType(), doc->getId())
+ DocumentUpdate(docMan.getTypeRepo(), *doc->getDataType(), doc->getId())
.addUpdate(FieldUpdate(field2)
- .addUpdate(MapValueUpdate(
- StringFieldValue("apple"),
- ArithmeticValueUpdate(ArithmeticValueUpdate::Sub, 1.0)
- )))
+ .addUpdate(MapValueUpdate(StringFieldValue("apple"),
+ ArithmeticValueUpdate(ArithmeticValueUpdate::Sub, 1.0))))
.applyTo(*doc);
- std::unique_ptr<WeightedSetFieldValue> fv4 =
- doc->getAs<WeightedSetFieldValue>(field2);
+ auto fv4 = doc->getAs<WeightedSetFieldValue>(field2);
CPPUNIT_ASSERT(fv4->find(StringFieldValue("apple")) == fv4->end());
}
@@ -965,9 +902,8 @@ DocumentUpdateTest::testTensorAssignUpdate()
Document updated(*doc);
FieldValue::UP new_value(createTensorFieldValue());
testValueUpdate(AssignValueUpdate(*new_value), *DataType::TENSOR);
- DocumentUpdate upd(*doc->getDataType(), doc->getId());
- upd.addUpdate(FieldUpdate(upd.getType().getField("tensor")).
- addUpdate(AssignValueUpdate(*new_value)));
+ DocumentUpdate upd(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
+ upd.addUpdate(FieldUpdate(upd.getType().getField("tensor")).addUpdate(AssignValueUpdate(*new_value)));
upd.applyTo(updated);
FieldValue::UP fval(updated.getValue("tensor"));
CPPUNIT_ASSERT(fval);
@@ -983,9 +919,8 @@ DocumentUpdateTest::testTensorClearUpdate()
Document updated(*doc);
updated.setValue(updated.getField("tensor"), *createTensorFieldValue());
CPPUNIT_ASSERT(*doc != updated);
- DocumentUpdate upd(*doc->getDataType(), doc->getId());
- upd.addUpdate(FieldUpdate(upd.getType().getField("tensor")).
- addUpdate(ClearValueUpdate()));
+ DocumentUpdate upd(docMan.getTypeRepo(), *doc->getDataType(), doc->getId());
+ upd.addUpdate(FieldUpdate(upd.getType().getField("tensor")).addUpdate(ClearValueUpdate()));
upd.applyTo(updated);
CPPUNIT_ASSERT(!updated.getValue("tensor"));
CPPUNIT_ASSERT(*doc == updated);
@@ -1036,12 +971,11 @@ struct CreateIfNonExistentFixture
CreateIfNonExistentFixture();
};
-CreateIfNonExistentFixture::~CreateIfNonExistentFixture() {}
+CreateIfNonExistentFixture::~CreateIfNonExistentFixture() = default;
CreateIfNonExistentFixture::CreateIfNonExistentFixture()
: docMan(),
document(docMan.createDocument()),
- update(new DocumentUpdate(*document->getDataType(),
- document->getId()))
+ update(new DocumentUpdate(docMan.getTypeRepo(), *document->getDataType(), document->getId()))
{
update->addUpdate(FieldUpdate(document->getField("headerval"))
.addUpdate(AssignValueUpdate(IntFieldValue(1))));
@@ -1069,7 +1003,8 @@ DocumentUpdateTest::testThatCreateIfNonExistentFlagIsSerializedAndDeserialized()
ByteBuffer::UP buf(serialize42(*f.update));
buf->flip();
- DocumentUpdate::UP deserialized = DocumentUpdate::create42(f.docMan.getTypeRepo(), *buf);
+ nbostream is(buf->getBufferAtPos(), buf->getRemaining());
+ auto deserialized = DocumentUpdate::create42(f.docMan.getTypeRepo(), is);
CPPUNIT_ASSERT_EQUAL(*f.update, *deserialized);
CPPUNIT_ASSERT(deserialized->getCreateIfNonExistent());
}
@@ -1089,7 +1024,7 @@ ArrayUpdateFixture::ArrayUpdateFixture()
doc(doc_man.createDocument()),
array_field(doc->getType().getField("tags")) // of type array<string>
{
- update = std::make_unique<DocumentUpdate>(*doc->getDataType(), doc->getId());
+ update = std::make_unique<DocumentUpdate>(doc_man.getTypeRepo(), *doc->getDataType(), doc->getId());
update->addUpdate(FieldUpdate(array_field)
.addUpdate(MapValueUpdate(IntFieldValue(1),
AssignValueUpdate(StringFieldValue("bar")))));
diff --git a/document/src/tests/fieldpathupdatetestcase.cpp b/document/src/tests/fieldpathupdatetestcase.cpp
index b240f322e4b..80a63a86b92 100644
--- a/document/src/tests/fieldpathupdatetestcase.cpp
+++ b/document/src/tests/fieldpathupdatetestcase.cpp
@@ -371,7 +371,7 @@ FieldPathUpdateTestCase::testRemoveField()
doc->setValue("strfoo", StringFieldValue("cocacola"));
CPPUNIT_ASSERT_EQUAL(vespalib::string("cocacola"), doc->getValue("strfoo")->getAsString());
//doc->print(std::cerr, true, "");
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new RemoveFieldPathUpdate("strfoo")));
docUp.applyTo(*doc);
CPPUNIT_ASSERT(doc->hasValue("strfoo") == false);
@@ -392,7 +392,7 @@ FieldPathUpdateTestCase::testApplyRemoveMultiList()
}
CPPUNIT_ASSERT(doc->hasValue("strarray"));
//doc->print(std::cerr, true, "");
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new RemoveFieldPathUpdate("strarray[$x]", "foobar.strarray[$x] == \"remove val 1\"")));
docUp.applyTo(*doc);
@@ -417,7 +417,7 @@ FieldPathUpdateTestCase::testApplyRemoveEntireListField()
doc->setValue("strarray", strArray);
}
//doc->print(std::cerr, true, "");
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new RemoveFieldPathUpdate("strarray", "")));
docUp.applyTo(*doc);
CPPUNIT_ASSERT(!doc->hasValue("strarray"));
@@ -436,7 +436,7 @@ FieldPathUpdateTestCase::testApplyRemoveMultiWset()
}
CPPUNIT_ASSERT(doc->hasValue("strwset"));
//doc->print(std::cerr, true, "");
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new RemoveFieldPathUpdate("strwset{remove val 1}")));
docUp.applyTo(*doc);
{
@@ -452,14 +452,14 @@ FieldPathUpdateTestCase::testApplyAssignSingle()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:drekka:karsk")));
CPPUNIT_ASSERT(doc->hasValue("strfoo") == false);
// Test assignment of non-existing
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*doc->getDataType(), "strfoo", std::string(), StringFieldValue("himert"))));
docUp.applyTo(*doc);
CPPUNIT_ASSERT(doc->hasValue("strfoo"));
CPPUNIT_ASSERT_EQUAL(vespalib::string("himert"), doc->getValue("strfoo")->getAsString());
// Test overwriting existing
- DocumentUpdate docUp2(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp2(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp2.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*doc->getDataType(), "strfoo", std::string(), StringFieldValue("wunderbaum"))));
docUp2.applyTo(*doc);
@@ -472,7 +472,7 @@ FieldPathUpdateTestCase::testApplyAssignMath()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:bat:man")));
doc->setValue("num", IntFieldValue(34));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("num", "", "($value * 2) / $value")));
docUp.applyTo(*doc);
CPPUNIT_ASSERT_EQUAL(static_cast<const FieldValue&>(IntFieldValue(2)), *doc->getValue("num"));
@@ -484,7 +484,7 @@ FieldPathUpdateTestCase::testApplyAssignMathByteToZero()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:bat:man")));
doc->setValue("byteval", ByteFieldValue(3));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("byteval", "", "$value - 3")));
docUp.applyTo(*doc);
CPPUNIT_ASSERT_EQUAL(static_cast<const FieldValue&>(ByteFieldValue(0)), *doc->getValue("byteval"));
@@ -497,7 +497,7 @@ FieldPathUpdateTestCase::testApplyAssignMathNotModifiedOnUnderflow()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:bat:man")));
doc->setValue("byteval", ByteFieldValue(low_value));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("byteval", "", "$value - 4")));
docUp.applyTo(*doc);
// Over/underflow will happen. You must have control of your data types.
@@ -510,7 +510,7 @@ FieldPathUpdateTestCase::testApplyAssignMathNotModifiedOnOverflow()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:bat:man")));
doc->setValue("byteval", ByteFieldValue(127));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("byteval", "", "$value + 200")));
docUp.applyTo(*doc);
// Over/underflow will happen. You must have control of your data types.
@@ -524,7 +524,7 @@ FieldPathUpdateTestCase::testApplyAssignMathDivZero()
CPPUNIT_ASSERT(doc->hasValue("num") == false);
doc->setValue("num", IntFieldValue(10));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("num", "", "$value / ($value - 10)")));
docUp.applyTo(*doc);
CPPUNIT_ASSERT_EQUAL(static_cast<const FieldValue&>(IntFieldValue(10)), *doc->getValue("num"));
@@ -538,7 +538,7 @@ FieldPathUpdateTestCase::testApplyAssignFieldNotExistingInExpression()
CPPUNIT_ASSERT(doc->hasValue("num") == false);
doc->setValue("num", IntFieldValue(10));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("num", "", "foobar.num2 + $value")));
docUp.applyTo(*doc);
CPPUNIT_ASSERT_EQUAL(static_cast<const FieldValue&>(IntFieldValue(10)), *doc->getValue("num"));
@@ -550,7 +550,7 @@ FieldPathUpdateTestCase::testApplyAssignFieldNotExistingInPath()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:bat:man")));
doc->setRepo(*_repo);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
try {
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("nosuchnum", "", "foobar.num + $value")));
docUp.applyTo(*doc);
@@ -565,7 +565,7 @@ FieldPathUpdateTestCase::testApplyAssignTargetNotExisting()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:bat:man")));
CPPUNIT_ASSERT(doc->hasValue("num") == false);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("num", "", "$value + 5")));
docUp.applyTo(*doc);
CPPUNIT_ASSERT_EQUAL(static_cast<const FieldValue&>(IntFieldValue(5)), *doc->getValue("num"));
@@ -582,7 +582,7 @@ FieldPathUpdateTestCase::testAssignSimpleMapValueWithVariable()
mfv.put(StringFieldValue("baz"), StringFieldValue("bananas"));
doc->setValue("strmap", mfv);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
// Select on value, not key
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*doc->getDataType(),
@@ -608,7 +608,7 @@ FieldPathUpdateTestCase::testApplyAssignMathRemoveIfZero()
doc->setValue("num", IntFieldValue(34));
CPPUNIT_ASSERT(doc->hasValue("num") == true);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
FieldPathUpdate::CP up1(new AssignFieldPathUpdate("num", "", "($value * 2) / $value - 2"));
static_cast<AssignFieldPathUpdate&>(*up1).setRemoveIfZero(true);
docUp.addFieldPathUpdate(up1);
@@ -635,7 +635,7 @@ FieldPathUpdateTestCase::testApplyAssignMultiList()
updateArray.add(StringFieldValue("assigned val 0"));
updateArray.add(StringFieldValue("assigned val 1"));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*doc->getDataType(), "strarray", std::string(), updateArray)));
docUp.applyTo(*doc);
@@ -667,7 +667,7 @@ FieldPathUpdateTestCase::testApplyAssignMultiWset()
assignWset.add(StringFieldValue("assigned val 0"), 5);
assignWset.add(StringFieldValue("assigned val 1"), 10);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*doc->getDataType(), "strwset", std::string(), assignWset)));
//doc->print(std::cerr, true, "");
@@ -696,7 +696,7 @@ FieldPathUpdateTestCase::testAssignWsetRemoveIfZero()
}
{
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
IntFieldValue zeroWeight(0);
FieldPathUpdate::CP assignUpdate(
new AssignFieldPathUpdate(*doc->getDataType(), "strwset{you say goodbye}", std::string(), zeroWeight));
@@ -724,7 +724,7 @@ FieldPathUpdateTestCase::testApplyAddMultiList()
adds.add(StringFieldValue("a festivus for the rest of us"));
adds.add(StringFieldValue("george is getting upset!"));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AddFieldPathUpdate(*doc->getDataType(), "strarray", std::string(), adds)));
//doc->print(std::cerr, true, "");
@@ -747,7 +747,7 @@ FieldPathUpdateTestCase::testAddAndAssignList()
CPPUNIT_ASSERT(doc->hasValue("strarray"));
}
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*doc->getDataType(),
"strarray[1]", std::string(), StringFieldValue("assigned val 1"))));
@@ -829,7 +829,7 @@ FieldPathUpdateTestCase::testAssignMap()
Keys k;
Fixture f(_foobar_type, k);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*f.doc->getDataType(), "structmap{" + k.key2 + "}", std::string(), f.fv4)));
docUp.applyTo(*f.doc);
@@ -850,7 +850,7 @@ FieldPathUpdateTestCase::testAssignMapStruct()
Keys k;
Fixture f(_foobar_type, k);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*f.doc->getDataType(), "structmap{" + k.key2 + "}.rating",
std::string(), IntFieldValue(48))));
@@ -872,7 +872,7 @@ FieldPathUpdateTestCase::testAssignMapStructVariable()
Keys k;
Fixture f(_foobar_type, k);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*f.doc->getDataType(), "structmap{$x}.rating",
"foobar.structmap{$x}.title == \"farnsworth\"", IntFieldValue(48))));
@@ -899,7 +899,7 @@ FieldPathUpdateTestCase::testAssignMapNoExist()
fv1.setValue("title", StringFieldValue("fry"));
fv1.setValue("rating", IntFieldValue(30));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*doc->getDataType(), "structmap{foo}", std::string(), fv1)));
//doc->print(std::cerr, true, "");
@@ -922,7 +922,7 @@ FieldPathUpdateTestCase::testAssignMapNoExistNoCreate()
fv1.setValue("title", StringFieldValue("fry"));
fv1.setValue("rating", IntFieldValue(30));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
FieldPathUpdate::CP assignUpdate(
new AssignFieldPathUpdate(*doc->getDataType(), "structmap{foo}", std::string(), fv1));
static_cast<AssignFieldPathUpdate&>(*assignUpdate).setCreateMissingPath(false);
@@ -944,7 +944,7 @@ FieldPathUpdateTestCase::testQuotedStringKey()
const char field_path[] = "structmap{\"here is a \\\"fancy\\\" 'map' :-} key :-{\"}";
Fixture f(_foobar_type, k);
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(
new AssignFieldPathUpdate(*f.doc->getDataType(), field_path, std::string(), f.fv4)));
docUp.applyTo(*f.doc);
@@ -970,8 +970,8 @@ FieldPathUpdateTestCase::testEqualityComparison()
fv4.setValue("rating", IntFieldValue(95));
{
- DocumentUpdate docUp1(_foobar_type, DocumentId("doc:barbar:foofoo"));
- DocumentUpdate docUp2(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp1(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp2(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
CPPUNIT_ASSERT(docUp1 == docUp2);
FieldPathUpdate::CP assignUp1(new AssignFieldPathUpdate(*doc->getDataType(),
@@ -982,8 +982,8 @@ FieldPathUpdateTestCase::testEqualityComparison()
CPPUNIT_ASSERT(docUp1 == docUp2);
}
{
- DocumentUpdate docUp1(_foobar_type, DocumentId("doc:barbar:foofoo"));
- DocumentUpdate docUp2(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp1(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp2(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
// where-clause diff
FieldPathUpdate::CP assignUp1(new AssignFieldPathUpdate(*doc->getDataType(),
"structmap{here be dragons}", std::string(), fv4));
@@ -994,8 +994,8 @@ FieldPathUpdateTestCase::testEqualityComparison()
CPPUNIT_ASSERT(docUp1 != docUp2);
}
{
- DocumentUpdate docUp1(_foobar_type, DocumentId("doc:barbar:foofoo"));
- DocumentUpdate docUp2(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp1(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp2(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
// fieldpath diff
FieldPathUpdate::CP assignUp1(new AssignFieldPathUpdate(*doc->getDataType(),
"structmap{here be dragons}", std::string(), fv4));
@@ -1020,7 +1020,7 @@ FieldPathUpdateTestCase::testAffectsDocumentBody()
// structmap is body field
{
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
FieldPathUpdate::CP update1(new AssignFieldPathUpdate(*doc->getDataType(),
"structmap{janitor}", std::string(), fv4));
@@ -1030,7 +1030,7 @@ FieldPathUpdateTestCase::testAffectsDocumentBody()
// strfoo is header field
{
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
FieldPathUpdate::CP update1(new AssignFieldPathUpdate(*doc->getDataType(),
"strfoo", std::string(), StringFieldValue("helloworld")));
static_cast<AssignFieldPathUpdate&>(*update1).setCreateMissingPath(true);
@@ -1045,7 +1045,7 @@ FieldPathUpdateTestCase::testIncompatibleDataTypeFails()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:things:stuff")));
MapFieldValue mfv(doc->getType().getField("structmap").getDataType());
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
try {
FieldPathUpdate::CP update1(new AssignFieldPathUpdate(*doc->getDataType(), "structmap{foo}",
@@ -1066,7 +1066,7 @@ FieldPathUpdateTestCase::testSerializeAssign()
val.setValue("title", StringFieldValue("cool frog"));
val.setValue("rating", IntFieldValue(100));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
FieldPathUpdate::CP update1(new AssignFieldPathUpdate(*doc->getDataType(), "structmap{ribbit}", "true", val));
static_cast<AssignFieldPathUpdate&>(*update1).setCreateMissingPath(true);
@@ -1086,7 +1086,7 @@ FieldPathUpdateTestCase::testSerializeAdd()
adds.add(StringFieldValue("a festivus for the rest of us"));
adds.add(StringFieldValue("george is getting upset!"));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
FieldPathUpdate::CP update1(new AddFieldPathUpdate(*doc->getDataType(), "strarray", std::string(), adds));
docUp.addFieldPathUpdate(update1);
@@ -1100,7 +1100,7 @@ FieldPathUpdateTestCase::testSerializeRemove()
Document::UP doc(new Document(_foobar_type, DocumentId("doc:weloveto:serializestuff")));
MapFieldValue mfv(doc->getType().getField("structmap").getDataType());
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
FieldPathUpdate::CP update1(new RemoveFieldPathUpdate("structmap{ribbit}", std::string()));
docUp.addFieldPathUpdate(update1);
@@ -1115,7 +1115,7 @@ FieldPathUpdateTestCase::testSerializeAssignMath()
CPPUNIT_ASSERT(doc->hasValue("num") == false);
doc->setValue("num", IntFieldValue(34));
- DocumentUpdate docUp(_foobar_type, DocumentId("doc:barbar:foofoo"));
+ DocumentUpdate docUp(*_repo, _foobar_type, DocumentId("doc:barbar:foofoo"));
docUp.addFieldPathUpdate(FieldPathUpdate::CP(new AssignFieldPathUpdate("num", "", "($value * 2) / $value")));
testSerialize(*_repo, docUp);
}
@@ -1124,7 +1124,7 @@ DocumentUpdate::UP
FieldPathUpdateTestCase::createDocumentUpdateForSerialization(const DocumentTypeRepo& repo)
{
const DocumentType *docType(repo.getDocumentType("serializetest"));
- DocumentUpdate::UP docUp(new DocumentUpdate(*docType, DocumentId("doc:serialization:xlanguage")));
+ DocumentUpdate::UP docUp(new DocumentUpdate(repo, *docType, DocumentId("doc:serialization:xlanguage")));
FieldPathUpdate::CP assign(new AssignFieldPathUpdate("intfield", "", "3"));
static_cast<AssignFieldPathUpdate&>(*assign).setRemoveIfZero(true);
diff --git a/document/src/tests/testxml.cpp b/document/src/tests/testxml.cpp
index 4cc1306ff45..09c2ef86279 100644
--- a/document/src/tests/testxml.cpp
+++ b/document/src/tests/testxml.cpp
@@ -73,7 +73,7 @@ createTestDocumentUpdate(const DocumentTypeRepo& repo)
const DocumentType* type(repo.getDocumentType("testdoc"));
DocumentId id("doc:crawler/http://www.ntnu.no/");
- DocumentUpdate::UP up(new DocumentUpdate(*type, id));
+ DocumentUpdate::UP up(new DocumentUpdate(repo, *type, id));
up->addUpdate(FieldUpdate(type->getField("intattr"))
.addUpdate(AssignValueUpdate(IntFieldValue(7))));
up->addUpdate(FieldUpdate(type->getField("stringattr"))
diff --git a/document/src/vespa/document/base/forcelink.cpp b/document/src/vespa/document/base/forcelink.cpp
index 8f683e40059..bc0097b68f4 100644
--- a/document/src/vespa/document/base/forcelink.cpp
+++ b/document/src/vespa/document/base/forcelink.cpp
@@ -13,7 +13,7 @@ ForceLink::ForceLink(void)
if (time(NULL) == 0) {
DocumentType type("foo", 1);
Document document(type, DocumentId("doc:ns:bar"));
- DocumentUpdate documentUpdate(type, DocumentId("doc:ns:bar"));
+ DocumentUpdate documentUpdate;
MapValueUpdate mapValueUpdate(IntFieldValue(3), ClearValueUpdate());
AddValueUpdate addValueUpdate(IntFieldValue(3));
RemoveValueUpdate removeValueUpdate(IntFieldValue(3));
diff --git a/document/src/vespa/document/serialization/vespadocumentserializer.cpp b/document/src/vespa/document/serialization/vespadocumentserializer.cpp
index 1a628ea2618..dac5ca4458b 100644
--- a/document/src/vespa/document/serialization/vespadocumentserializer.cpp
+++ b/document/src/vespa/document/serialization/vespadocumentserializer.cpp
@@ -439,17 +439,19 @@ void VespaDocumentSerializer::write42(const DocumentUpdate &value)
void VespaDocumentSerializer::writeHEAD(const DocumentUpdate &value)
{
+ if (!value._needHardReserialize) {
+ _stream.write(value._backing.peek(), value._backing.size());
+ return;
+ }
write(value.getId());
_stream.write(value.getType().getName().c_str(), value.getType().getName().size() + 1);
_stream << static_cast<uint16_t>(0);
- const DocumentUpdate::FieldUpdateV & updates(value.getUpdates());
- _stream << static_cast<uint32_t>(updates.size());
- for (const auto & update : updates) {
+ _stream << static_cast<uint32_t>(value._updates.size());
+ for (const auto & update : value._updates) {
write(update);
}
- const DocumentUpdate::FieldPathUpdateV & fieldPathUpdates(value.getFieldPathUpdates());
- _stream << static_cast<uint32_t>(value.serializeFlags(fieldPathUpdates.size()));
- for (const auto & update : fieldPathUpdates) {
+ _stream << static_cast<uint32_t>(value.serializeFlags(value._fieldPathUpdates.size()));
+ for (const auto & update : value._fieldPathUpdates) {
_stream << update->getSerializedType();
write(*update);
}
diff --git a/document/src/vespa/document/update/documentupdate.cpp b/document/src/vespa/document/update/documentupdate.cpp
index 30b760a6102..cb0beff6a15 100644
--- a/document/src/vespa/document/update/documentupdate.cpp
+++ b/document/src/vespa/document/update/documentupdate.cpp
@@ -25,59 +25,43 @@ namespace document {
// Declare content bits.
static const unsigned char CONTENT_HASTYPE = 0x01;
-DocumentUpdate::DocumentUpdate(const DataType &type, const DocumentId& id)
+DocumentUpdate::DocumentUpdate(const DocumentTypeRepo & repo, const DataType &type, const DocumentId& id)
: _documentId(id),
_type(&type),
+ _repo(&repo),
+ _backing(),
_updates(),
_fieldPathUpdates(),
_version(Document::getNewestSerializationVersion()),
- _createIfNonExistent(false)
+ _createIfNonExistent(false),
+ _needHardReserialize(false)
{
if (!type.getClass().inherits(DocumentType::classId)) {
- throw IllegalArgumentException("Cannot generate a document with non-document type " + type.toString() + ".",
- VESPA_STRLOC);
+ throw IllegalArgumentException("Cannot generate a document with non-document type " + type.toString() + ".", VESPA_STRLOC);
}
+ serializeHeader();
}
-DocumentUpdate::DocumentUpdate(const DocumentTypeRepo& repo,
- ByteBuffer& buffer,
- SerializeVersion serializeVersion)
- : _documentId("doc::"),
+DocumentUpdate::DocumentUpdate()
+ : _documentId(),
_type(DataType::DOCUMENT),
+ _repo(nullptr),
+ _backing(),
_updates(),
+ _fieldPathUpdates(),
_version(Document::getNewestSerializationVersion()),
- _createIfNonExistent(false)
+ _createIfNonExistent(false),
+ _needHardReserialize(false)
{
- switch (serializeVersion) {
- case SerializeVersion::SERIALIZE_HEAD:
- deserializeHEAD(repo, buffer);
- break;
- case SerializeVersion::SERIALIZE_42:
- deserialize42(repo, buffer);
- break;
- default:
- throw IllegalArgumentException("bad serializeVersion provided.", VESPA_STRLOC);
- }
}
DocumentUpdate::~DocumentUpdate() = default;
-
bool
DocumentUpdate::operator==(const DocumentUpdate& other) const
{
- if (_documentId != other._documentId) return false;
- if (*_type != *other._type) return false;
- if (_updates.size() != other._updates.size()) return false;
- for (std::size_t i = 0, n = _updates.size(); i < n; ++i) {
- if (_updates[i] != other._updates[i]) return false;
- }
- if (_fieldPathUpdates.size() != other._fieldPathUpdates.size()) return false;
- for (std::size_t i = 0, n = _fieldPathUpdates.size(); i < n; ++i) {
- if (*_fieldPathUpdates[i] != *other._fieldPathUpdates[i]) return false;
- }
- if (_createIfNonExistent != other._createIfNonExistent) return false;
- return true;
+ return (_backing.size() == other._backing.size()) &&
+ (memcmp(_backing.peek(), other._backing.peek(), _backing.size()) == 0);
}
const DocumentType&
@@ -85,22 +69,67 @@ DocumentUpdate::getType() const {
return static_cast<const DocumentType &> (*_type);
}
+const DocumentUpdate::FieldUpdateV &
+DocumentUpdate::getUpdates() const {
+ ensureDeserialized();
+ return _updates;
+}
+
+const DocumentUpdate::FieldPathUpdateV &
+DocumentUpdate::getFieldPathUpdates() const {
+ ensureDeserialized();
+ return _fieldPathUpdates;
+}
+
+void
+DocumentUpdate::eagerDeserialize() const {
+ ensureDeserialized();
+}
+
+void DocumentUpdate::lazyDeserialize(const DocumentTypeRepo & repo, nbostream & stream) {
+ size_t start(stream.rp());
+ deserializeHEAD(repo, stream);
+ stream.rp(start);
+}
+void DocumentUpdate::ensureDeserialized() const {
+ if (_updates.empty() && _fieldPathUpdates.empty()) {
+ const_cast<DocumentUpdate &>(*this).lazyDeserialize(*_repo, const_cast<nbostream &>(_backing));
+ }
+}
+
DocumentUpdate&
DocumentUpdate::addUpdate(const FieldUpdate& update) {
+ ensureDeserialized();
_updates.push_back(update);
+ reserialize();
return *this;
}
DocumentUpdate&
DocumentUpdate::addFieldPathUpdate(const FieldPathUpdate::CP& update) {
+ ensureDeserialized();
_fieldPathUpdates.push_back(update);
+ reserialize();
return *this;
}
void
-DocumentUpdate::print(std::ostream& out, bool verbose,
- const std::string& indent) const
+DocumentUpdate::setCreateIfNonExistent(bool value) {
+ ensureDeserialized();
+ _createIfNonExistent = value;
+ reserialize();
+}
+
+bool
+DocumentUpdate::getCreateIfNonExistent() const {
+ ensureDeserialized();
+ return _createIfNonExistent;
+}
+
+void
+DocumentUpdate::print(std::ostream& out, bool verbose, const std::string& indent) const
{
+ ensureDeserialized();
out << "DocumentUpdate(";
if (_type) {
_type->print(out, verbose, indent + " ");
@@ -131,6 +160,7 @@ DocumentUpdate::print(std::ostream& out, bool verbose,
void
DocumentUpdate::applyTo(Document& doc) const
{
+ ensureDeserialized();
const DocumentType& type = doc.getType();
if (_type->getName() != type.getName()) {
string err = make_string("Can not apply a \"%s\" document update to a \"%s\" document.",
@@ -150,6 +180,17 @@ DocumentUpdate::applyTo(Document& doc) const
}
void
+DocumentUpdate::serializeHeader() {
+ string id_string = _documentId.getScheme().toString();
+ _backing.write(id_string.data(), id_string.size());
+ _backing << static_cast<uint8_t>(0);
+ _backing.write(getType().getName().c_str(), getType().getName().size() + 1);
+ _backing << static_cast<uint16_t>(0); // version
+ _backing << static_cast<uint32_t>(0); // Number of updates
+ _backing << static_cast<uint32_t>(0); // Number of field path updates
+}
+
+void
DocumentUpdate::serializeHEAD(nbostream &stream) const
{
VespaDocumentSerializer serializer(stream);
@@ -165,92 +206,157 @@ DocumentUpdate::serializeFlags(int size_) const
}
namespace {
- std::pair<const DocumentType *, DocumentId>
- deserializeTypeAndId(const DocumentTypeRepo& repo, ByteBuffer& buffer) {
- nbostream stream(buffer.getBufferAtPos(), buffer.getRemaining());
- DocumentId docId(stream);
- buffer.incPos(stream.rp());
-
- // Read content bit vector.
- unsigned char content = 0x00;
- buffer.getByte(content);
-
- // Why on earth do we have this whether we have type part?
- // We need type for object to work, so just throwing exception if it's
- // not there.
- if((content & CONTENT_HASTYPE) == 0) {
- throw IllegalStateException("Missing document type", VESPA_STRLOC);
- }
- vespalib::stringref typestr = buffer.getBufferAtPos();
- buffer.incPos(typestr.length() + 1);
+vespalib::stringref
+readCStr(nbostream & stream) {
+ const char * s = stream.peek();
+ size_t sz = strnlen(s, stream.size());
+ stream.adjustReadPos(sz+1);
+ return vespalib::stringref(s, sz);
+}
- int16_t version = 0;
- buffer.getShortNetwork(version);
- const DocumentType *type = repo.getDocumentType(typestr);
- if (!type) {
- throw DocumentTypeNotFoundException(typestr, VESPA_STRLOC);
- }
- return std::make_pair(type, docId);
+std::pair<const DocumentType *, DocumentId>
+deserializeTypeAndId(const DocumentTypeRepo& repo, vespalib::nbostream & stream) {
+ DocumentId docId(stream);
+
+ // Read content bit vector.
+ unsigned char content = 0x00;
+ stream >> content;
+
+ // Why on earth do we have this whether we have type part?
+ // We need type for object to work, so just throwing exception if it's
+ // not there.
+ if((content & CONTENT_HASTYPE) == 0) {
+ throw IllegalStateException("Missing document type", VESPA_STRLOC);
}
+
+ vespalib::stringref typestr = readCStr(stream);
+
+ int16_t version = 0;
+ stream >> version;
+ const DocumentType *type = repo.getDocumentType(typestr);
+ if (!type) {
+ throw DocumentTypeNotFoundException(typestr, VESPA_STRLOC);
+ }
+ return std::make_pair(type, docId);
+}
}
// Deserialize the content of the given buffer into this document update.
DocumentUpdate::UP
-DocumentUpdate::create42(const DocumentTypeRepo& repo, ByteBuffer& buffer)
+DocumentUpdate::create42(const DocumentTypeRepo& repo, vespalib::nbostream & stream)
{
- return std::make_unique<DocumentUpdate>(repo, buffer, SerializeVersion::SERIALIZE_42);
+ auto update = std::make_unique<DocumentUpdate>();
+ update->init42(repo, stream);
+ return update;
}
DocumentUpdate::UP
DocumentUpdate::createHEAD(const DocumentTypeRepo& repo, ByteBuffer& buffer)
{
- return std::make_unique<DocumentUpdate>(repo, buffer, SerializeVersion::SERIALIZE_HEAD);
+ vespalib::nbostream is(buffer.getBufferAtPos(), buffer.getRemaining());
+ auto update = std::make_unique<DocumentUpdate>();
+ update->initHEAD(repo, is);
+ buffer.setPos(buffer.getPos() + is.rp());
+ return update;
+}
+
+DocumentUpdate::UP
+DocumentUpdate::createHEAD(const DocumentTypeRepo& repo, vespalib::nbostream stream)
+{
+ auto update = std::make_unique<DocumentUpdate>();
+ update->initHEAD(repo, std::move(stream));
+ return update;
}
void
-DocumentUpdate::deserialize42(const DocumentTypeRepo& repo, ByteBuffer& buffer)
+DocumentUpdate::init42(const DocumentTypeRepo & repo, vespalib::nbostream & stream)
{
- int pos = buffer.getPos();
- try{
- buffer.getShortNetwork(_version);
+ _repo = &repo;
+ deserialize42(repo, stream);
+ reserialize();
+}
+void
+DocumentUpdate::initHEAD(const DocumentTypeRepo & repo, vespalib::nbostream && stream)
+{
+ _repo = &repo;
+ _backing = std::move(stream);
+ size_t startPos = _backing.rp();
+ deserializeHeader(repo, _backing);
+ _backing.rp(startPos);
+}
- std::pair<const DocumentType *, DocumentId> typeAndId(deserializeTypeAndId(repo, buffer));
+void
+DocumentUpdate::initHEAD(const DocumentTypeRepo & repo, vespalib::nbostream & stream)
+{
+ size_t startPos = stream.rp();
+ deserializeHEAD(repo, stream);
+ size_t sz = stream.rp() - startPos;
+ _backing = nbostream(stream.peek() - sz, sz);
+}
+
+void
+DocumentUpdate::deserialize42(const DocumentTypeRepo& repo, vespalib::nbostream & stream)
+{
+ size_t pos = stream.rp();
+ try{
+ int16_t version(0);
+ stream >> version;
+ std::pair<const DocumentType *, DocumentId> typeAndId(deserializeTypeAndId(repo, stream));
_type = typeAndId.first;
_documentId = typeAndId.second;
// Read field updates, if any.
- if(buffer.getRemaining() > 0) {
- int sizeAndFlags = 0;
- buffer.getIntNetwork(sizeAndFlags);
+ if (! stream.empty()) {
+ int32_t sizeAndFlags = 0;
+ stream >> sizeAndFlags;
int numUpdates = deserializeFlags(sizeAndFlags);
_updates.reserve(numUpdates);
+ ByteBuffer buffer(stream.peek(), stream.size());
for (int i = 0; i < numUpdates; i++) {
_updates.emplace_back(repo, *typeAndId.first, buffer, _version);
}
+ stream.adjustReadPos(buffer.getPos());
}
} catch (const DeserializeException &) {
- buffer.setPos(pos);
+ stream.rp(pos);
throw;
} catch (const BufferOutOfBoundsException &) {
- buffer.setPos(pos);
+ stream.rp(pos);
throw;
}
}
void
-DocumentUpdate::deserializeHEAD(const DocumentTypeRepo &repo, ByteBuffer &buffer)
+DocumentUpdate::deserializeHeader(const DocumentTypeRepo &repo, vespalib::nbostream & stream)
{
- int pos = buffer.getPos();
+ assert(_updates.empty());
+ assert(_fieldPathUpdates.empty());
+ _documentId = DocumentId(stream);
+
+ vespalib::stringref typestr = readCStr(stream);
+ int16_t version = 0;
+ stream >> version;
+ const DocumentType *docType = repo.getDocumentType(typestr);
+ if (!docType) {
+ throw DocumentTypeNotFoundException(typestr, VESPA_STRLOC);
+ }
+ _type = docType;
+ _type = docType;
+}
+
+void
+DocumentUpdate::deserializeHEAD(const DocumentTypeRepo &repo, vespalib::nbostream & stream)
+{
+ _updates.clear();
+ _fieldPathUpdates.clear();
+ size_t pos = stream.rp();
try {
- nbostream stream(buffer.getBufferAtPos(), buffer.getRemaining());
_documentId = DocumentId(stream);
- buffer.incPos(stream.rp());
- vespalib::stringref typestr = buffer.getBufferAtPos();
- buffer.incPos(typestr.length() + 1);
+ vespalib::stringref typestr = readCStr(stream);
int16_t version = 0;
- buffer.getShortNetwork(version);
+ stream >> version;
const DocumentType *docType = repo.getDocumentType(typestr);
if (!docType) {
throw DocumentTypeNotFoundException(typestr, VESPA_STRLOC);
@@ -258,27 +364,31 @@ DocumentUpdate::deserializeHEAD(const DocumentTypeRepo &repo, ByteBuffer &buffer
_type = docType;
// Read field updates, if any.
- if (buffer.getRemaining() > 0) {
- int numUpdates = 0;
- buffer.getIntNetwork(numUpdates);
+ if ( ! stream.empty() ) {
+ int32_t numUpdates = 0;
+ stream >> numUpdates;
_updates.reserve(numUpdates);
+ ByteBuffer buffer(stream.peek(), stream.size());
for (int i = 0; i < numUpdates; i++) {
- _updates.emplace_back(repo, *docType, buffer, 8);
+ _updates.emplace_back(repo, *docType, buffer, _version);
}
+ stream.adjustReadPos(buffer.getPos());
}
// Read fieldpath updates, if any
- int sizeAndFlags = 0;
- buffer.getIntNetwork(sizeAndFlags);
+ int32_t sizeAndFlags = 0;
+ stream >> sizeAndFlags;
int numUpdates = deserializeFlags(sizeAndFlags);
_fieldPathUpdates.reserve(numUpdates);
+ ByteBuffer buffer(stream.peek(), stream.size());
for (int i = 0; i < numUpdates; ++i) {
- _fieldPathUpdates.emplace_back(FieldPathUpdate::createInstance(repo, *_type, buffer, 8).release());
+ _fieldPathUpdates.emplace_back(FieldPathUpdate::createInstance(repo, *_type, buffer, _version).release());
}
+ stream.adjustReadPos(buffer.getPos());
} catch (const DeserializeException &) {
- buffer.setPos(pos);
+ stream.rp(pos);
throw;
} catch (const BufferOutOfBoundsException &) {
- buffer.setPos(pos);
+ stream.rp(pos);
throw;
}
}
@@ -293,6 +403,7 @@ DocumentUpdate::deserializeFlags(int sizeAndFlags)
void
DocumentUpdate::printXml(XmlOutputStream& xos) const
{
+ ensureDeserialized();
xos << XmlTag("document")
<< XmlAttribute("type", _type->getName())
<< XmlAttribute("id", getId().toString());
@@ -304,4 +415,15 @@ DocumentUpdate::printXml(XmlOutputStream& xos) const
xos << XmlEndTag();
}
+void
+DocumentUpdate::reserialize()
+{
+ nbostream stream;
+ VespaDocumentSerializer serializer(stream);
+ _needHardReserialize = true;
+ serializer.writeHEAD(*this);
+ _backing = std::move(stream);
+ _needHardReserialize = false;
+}
+
}
diff --git a/document/src/vespa/document/update/documentupdate.h b/document/src/vespa/document/update/documentupdate.h
index c6250fb6b75..f791dceb496 100644
--- a/document/src/vespa/document/update/documentupdate.h
+++ b/document/src/vespa/document/update/documentupdate.h
@@ -41,16 +41,6 @@ class VespaDocumentSerializer;
*/
class DocumentUpdate final : public Printable, public XmlSerializable
{
-private:
- /**
- * Enum class containing the legal serialization version for
- * document updates. This version is not encoded in the serialized
- * document update.
- */
- enum class SerializeVersion {
- SERIALIZE_42, // old style format, before vespa 5.0
- SERIALIZE_HEAD // new style format, since vespa 5.0
- };
public:
typedef std::unique_ptr<DocumentUpdate> UP;
typedef std::shared_ptr<DocumentUpdate> SP;
@@ -60,12 +50,13 @@ public:
/**
* Create old style document update, no support for field path updates.
*/
- static DocumentUpdate::UP create42(const DocumentTypeRepo&, ByteBuffer&);
+ static DocumentUpdate::UP create42(const DocumentTypeRepo & repo, vespalib::nbostream & stream);
/**
* Create new style document update, possibly with field path updates.
*/
- static DocumentUpdate::UP createHEAD(const DocumentTypeRepo&, ByteBuffer&);
+ static DocumentUpdate::UP createHEAD(const DocumentTypeRepo & repo, vespalib::nbostream stream);
+ static DocumentUpdate::UP createHEAD(const DocumentTypeRepo & repo, ByteBuffer & buffer);
/**
* Create a document update from a byte buffer containing a serialized
@@ -75,7 +66,7 @@ public:
* @param buffer The buffer containing the serialized document update
* @param serializeVersion Selector between serialization formats.
*/
- DocumentUpdate(const DocumentTypeRepo &repo, ByteBuffer &buffer, SerializeVersion serializeVersion);
+ DocumentUpdate();
/**
* The document type is not strictly needed, as we know this at applyTo()
* time, but search does not use applyTo() code to do the update, and don't
@@ -86,7 +77,7 @@ public:
* @param type The document type that this update is applicable for.
* @param id The identifier of the document that this update is created for.
*/
- DocumentUpdate(const DataType &type, const DocumentId& id);
+ DocumentUpdate(const DocumentTypeRepo & repo, const DataType &type, const DocumentId& id);
DocumentUpdate(const DocumentUpdate &) = delete;
DocumentUpdate & operator = (const DocumentUpdate &) = delete;
@@ -104,63 +95,61 @@ public:
* type as this.
*/
void applyTo(Document& doc) const;
-
- /**
- * Add a field update to this document update.
- * @return A reference to this.
- */
- DocumentUpdate& addUpdate(const FieldUpdate& update);
- /**
- * Add a fieldpath update to this document update.
- * @return A reference to this.
- */
+ DocumentUpdate& addUpdate(const FieldUpdate& update);
DocumentUpdate& addFieldPathUpdate(const FieldPathUpdate::CP& update);
/** @return The list of updates. */
- const FieldUpdateV & getUpdates() const { return _updates; }
+ const FieldUpdateV & getUpdates() const;
/** @return The list of fieldpath updates. */
- const FieldPathUpdateV & getFieldPathUpdates() const { return _fieldPathUpdates; }
+ const FieldPathUpdateV & getFieldPathUpdates() const;
+
+ void eagerDeserialize() const;
/** @return The type of document this update is for. */
const DocumentType& getType() const;
-
void print(std::ostream& out, bool verbose, const std::string& indent) const override;
-
void serializeHEAD(vespalib::nbostream &stream) const;
-
void printXml(XmlOutputStream&) const override;
/**
* Sets whether this update should create the document it updates if that document does not exist.
* In this case an empty document is created before the update is applied.
*/
- void setCreateIfNonExistent(bool value) {
- _createIfNonExistent = value;
- }
+ void setCreateIfNonExistent(bool value);
/**
* Gets whether this update should create the document it updates if that document does not exist.
*/
- bool getCreateIfNonExistent() const {
- return _createIfNonExistent;
- }
+ bool getCreateIfNonExistent() const;
int serializeFlags(int size_) const;
int16_t getVersion() const { return _version; }
private:
- DocumentId _documentId; // The ID of the document to update.
- const DataType *_type; // The type of document this update is for.
- FieldUpdateV _updates; // The list of field updates.
- FieldPathUpdateV _fieldPathUpdates;
- int16_t _version; // Serialization version
- bool _createIfNonExistent;
+ DocumentId _documentId; // The ID of the document to update.
+ const DataType *_type; // The type of document this update is for.
+ const DocumentTypeRepo *_repo;
+ vespalib::nbostream _backing;
+ FieldUpdateV _updates; // The list of field updates.
+ FieldPathUpdateV _fieldPathUpdates;
+ const int16_t _version; // Serialization version
+ bool _createIfNonExistent;
+ bool _needHardReserialize;
int deserializeFlags(int sizeAndFlags);
- void deserialize42(const DocumentTypeRepo&, ByteBuffer&);
- void deserializeHEAD(const DocumentTypeRepo&, ByteBuffer&);
+ void init42(const DocumentTypeRepo & repo, vespalib::nbostream & stream);
+ void initHEAD(const DocumentTypeRepo & repo, vespalib::nbostream && stream);
+ void initHEAD(const DocumentTypeRepo & repo, vespalib::nbostream & stream);
+ void deserialize42(const DocumentTypeRepo & repo, vespalib::nbostream & stream);
+ void deserializeHEAD(const DocumentTypeRepo & repo, vespalib::nbostream & stream);
+ void lazyDeserialize(const DocumentTypeRepo & repo, vespalib::nbostream & stream);
+ void ensureDeserialized() const;
+ void serializeHeader();
+ void reserialize();
+ void deserializeHeader(const DocumentTypeRepo & repo, vespalib::nbostream & stream);
+ friend VespaDocumentSerializer;
};
} // document