diff options
32 files changed, 450 insertions, 428 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..7673782dba4 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); + _backing << static_cast<uint32_t>(0); + _backing << static_cast<uint32_t>(0); +} + +void DocumentUpdate::serializeHEAD(nbostream &stream) const { VespaDocumentSerializer serializer(stream); @@ -165,92 +206,147 @@ 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); - } +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 = buffer.getBufferAtPos(); - buffer.incPos(typestr.length() + 1); + vespalib::stringref typestr = stream.peek(); + stream.adjustReadPos(typestr.length() + 1); - 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); + 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); +} + +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); +} - std::pair<const DocumentType *, DocumentId> typeAndId(deserializeTypeAndId(repo, buffer)); +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) { + if (! stream.empty()) { int sizeAndFlags = 0; - buffer.getIntNetwork(sizeAndFlags); + 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) +{ + assert(_updates.empty()); + assert(_fieldPathUpdates.empty()); + _documentId = DocumentId(stream); + + vespalib::stringref typestr = stream.peek(); + stream.adjustReadPos(typestr.length() + 1); + int16_t version = 0; + stream >> version; + const DocumentType *docType = repo.getDocumentType(typestr); + _type = docType; +} + +void +DocumentUpdate::deserializeHEAD(const DocumentTypeRepo &repo, vespalib::nbostream & stream) { - int pos = buffer.getPos(); + _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 = stream.peek(); + stream.adjustReadPos(typestr.length() + 1); int16_t version = 0; - buffer.getShortNetwork(version); + stream >> version; const DocumentType *docType = repo.getDocumentType(typestr); if (!docType) { throw DocumentTypeNotFoundException(typestr, VESPA_STRLOC); @@ -258,27 +354,31 @@ DocumentUpdate::deserializeHEAD(const DocumentTypeRepo &repo, ByteBuffer &buffer _type = docType; // Read field updates, if any. - if (buffer.getRemaining() > 0) { + if ( ! stream.empty() ) { int numUpdates = 0; - buffer.getIntNetwork(numUpdates); + 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); + 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 +393,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 +405,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 diff --git a/documentapi/src/tests/messagebus/messagebus_test.cpp b/documentapi/src/tests/messagebus/messagebus_test.cpp index cd2820d8c05..dff3f3f1bac 100644 --- a/documentapi/src/tests/messagebus/messagebus_test.cpp +++ b/documentapi/src/tests/messagebus/messagebus_test.cpp @@ -59,7 +59,7 @@ void Test::testMessage() { // Test one update. UpdateDocumentMessage upd1( document::DocumentUpdate::SP( - new document::DocumentUpdate(*testdoc_type, + new document::DocumentUpdate(*_repo, *testdoc_type, document::DocumentId(document::DocIdString( "testdoc", "testme1"))))); @@ -80,7 +80,7 @@ void Test::testMessage() { // Compare to another. UpdateDocumentMessage upd2( document::DocumentUpdate::SP( - new document::DocumentUpdate(*testdoc_type, + new document::DocumentUpdate(*_repo, *testdoc_type, document::DocumentId(document::DocIdString( "testdoc", "testme2"))))); EXPECT_TRUE(!(upd1.getDocumentUpdate().getId() == upd2.getDocumentUpdate().getId())); diff --git a/documentapi/src/tests/messages/messages50test.cpp b/documentapi/src/tests/messages/messages50test.cpp index 48728ff6057..6705277d5c3 100644 --- a/documentapi/src/tests/messages/messages50test.cpp +++ b/documentapi/src/tests/messages/messages50test.cpp @@ -672,8 +672,7 @@ Messages50Test::testUpdateDocumentMessage() { const DocumentTypeRepo &repo = getTypeRepo(); const document::DocumentType &docType = *repo.getDocumentType("testdoc"); - document::DocumentUpdate::SP - upd(new document::DocumentUpdate(docType, document::DocumentId("doc:scheme:"))); + auto upd(std::make_shared<document::DocumentUpdate>(repo, docType, document::DocumentId("doc:scheme:"))); upd->addFieldPathUpdate(document::FieldPathUpdate::CP( new document::RemoveFieldPathUpdate("intfield", "testdoc.intfield > 0"))); UpdateDocumentMessage msg(upd); @@ -682,7 +681,7 @@ Messages50Test::testUpdateDocumentMessage() EXPECT_EQUAL(MESSAGE_BASE_LENGTH + 89u, serialize("UpdateDocumentMessage", msg)); for (uint32_t lang = 0; lang < NUM_LANGUAGES; ++lang) { mbus::Routable::UP obj = deserialize("UpdateDocumentMessage", DocumentProtocol::MESSAGE_UPDATEDOCUMENT, lang); - if (EXPECT_TRUE(obj.get() != NULL)) { + if (EXPECT_TRUE(obj.get() != nullptr)) { UpdateDocumentMessage &ref = static_cast<UpdateDocumentMessage&>(*obj); EXPECT_EQUAL(*upd, ref.getDocumentUpdate()); EXPECT_EQUAL(666u, ref.getOldTimestamp()); @@ -703,21 +702,21 @@ Messages50Test::testBatchDocumentUpdateMessage() { document::DocumentUpdate::SP upd; - upd.reset(new document::DocumentUpdate(docType, document::DocumentId("userdoc:footype:1234:foo"))); + upd.reset(new document::DocumentUpdate(repo, docType, document::DocumentId("userdoc:footype:1234:foo"))); upd->addFieldPathUpdate(document::FieldPathUpdate::CP( new document::RemoveFieldPathUpdate("intfield", "testdoc.intfield > 0"))); msg.addUpdate(upd); } { document::DocumentUpdate::SP upd; - upd.reset(new document::DocumentUpdate(docType, document::DocumentId("orderdoc(32,17):footype:1234:123456789:foo"))); + upd.reset(new document::DocumentUpdate(repo, docType, document::DocumentId("orderdoc(32,17):footype:1234:123456789:foo"))); upd->addFieldPathUpdate(document::FieldPathUpdate::CP( new document::RemoveFieldPathUpdate("intfield", "testdoc.intfield > 0"))); msg.addUpdate(upd); } try { document::DocumentUpdate::SP upd; - upd.reset(new document::DocumentUpdate(docType, document::DocumentId("userdoc:footype:5678:foo"))); + upd.reset(new document::DocumentUpdate(repo, docType, document::DocumentId("userdoc:footype:5678:foo"))); upd->addFieldPathUpdate(document::FieldPathUpdate::CP( new document::RemoveFieldPathUpdate("intfield", "testdoc.intfield > 0"))); msg.addUpdate(upd); @@ -726,7 +725,7 @@ Messages50Test::testBatchDocumentUpdateMessage() } try { document::DocumentUpdate::SP upd; - upd.reset(new document::DocumentUpdate(docType, document::DocumentId("groupdoc:footype:hable:foo"))); + upd.reset(new document::DocumentUpdate(repo, docType, document::DocumentId("groupdoc:footype:hable:foo"))); upd->addFieldPathUpdate(document::FieldPathUpdate::CP( new document::RemoveFieldPathUpdate("intfield", "testdoc.intfield > 0"))); msg.addUpdate(upd); diff --git a/documentapi/src/tests/messages/messages52test.cpp b/documentapi/src/tests/messages/messages52test.cpp index eaf8bbec8c4..8f5d7381500 100644 --- a/documentapi/src/tests/messages/messages52test.cpp +++ b/documentapi/src/tests/messages/messages52test.cpp @@ -91,7 +91,7 @@ Messages52Test::testUpdateDocumentMessage() const DocumentTypeRepo & repo = getTypeRepo(); const document::DocumentType & docType = *repo.getDocumentType("testdoc"); - auto docUpdate = std::make_shared<document::DocumentUpdate>(docType, document::DocumentId("doc:scheme:")); + auto docUpdate = std::make_shared<document::DocumentUpdate>(repo, docType, document::DocumentId("doc:scheme:")); docUpdate->addFieldPathUpdate(document::FieldPathUpdate::CP( new document::RemoveFieldPathUpdate("intfield", "testdoc.intfield > 0"))); diff --git a/documentapi/src/tests/policies/policies_test.cpp b/documentapi/src/tests/policies/policies_test.cpp index 7852136dfc7..3e804c30415 100644 --- a/documentapi/src/tests/policies/policies_test.cpp +++ b/documentapi/src/tests/policies/policies_test.cpp @@ -621,7 +621,7 @@ Test::testDocumentRouteSelector() EXPECT_TRUE(frame.testSelect(StringList().add("foo").add("bar"))); frame.setMessage(make_unique<UpdateDocumentMessage>( - make_shared<DocumentUpdate>(*_docType, DocumentId("doc:scheme:")))); + make_shared<DocumentUpdate>(*_repo, *_docType, DocumentId("doc:scheme:")))); EXPECT_TRUE(frame.testSelect(StringList().add("foo"))); put = make_unique<PutDocumentMessage>(make_shared<Document>(*_docType, DocumentId("doc:scheme:"))); @@ -650,7 +650,7 @@ Test::testDocumentRouteSelectorIgnore() EXPECT_EQUAL(0u, reply->getNumErrors()); frame.setMessage(make_unique<UpdateDocumentMessage>( - make_shared<DocumentUpdate>(*_docType, DocumentId("doc:scheme:")))); + make_shared<DocumentUpdate>(*_repo, *_docType, DocumentId("doc:scheme:")))); EXPECT_TRUE(frame.testSelect(StringList().add("docproc/cluster.foo"))); } diff --git a/persistence/src/vespa/persistence/conformancetest/conformancetest.cpp b/persistence/src/vespa/persistence/conformancetest/conformancetest.cpp index f9538a94c59..c1373a391f0 100644 --- a/persistence/src/vespa/persistence/conformancetest/conformancetest.cpp +++ b/persistence/src/vespa/persistence/conformancetest/conformancetest.cpp @@ -897,10 +897,8 @@ void ConformanceTest::testUpdate() { const document::DocumentType *docType( testDocMan.getTypeRepo().getDocumentType("testdoctype1")); - document::DocumentUpdate::SP - update(new DocumentUpdate(*docType, doc1->getId())); - std::shared_ptr<document::AssignValueUpdate> assignUpdate( - new document::AssignValueUpdate(document::IntFieldValue(42))); + document::DocumentUpdate::SP update(new DocumentUpdate(testDocMan.getTypeRepo(), *docType, doc1->getId())); + std::shared_ptr<document::AssignValueUpdate> assignUpdate(new document::AssignValueUpdate(document::IntFieldValue(42))); document::FieldUpdate fieldUpdate(docType->getField("headerval")); fieldUpdate.addUpdate(*assignUpdate); update->addUpdate(fieldUpdate); diff --git a/searchcore/src/tests/proton/attribute/attribute_test.cpp b/searchcore/src/tests/proton/attribute/attribute_test.cpp index c41b6bdcb97..0e6bd2c74fe 100644 --- a/searchcore/src/tests/proton/attribute/attribute_test.cpp +++ b/searchcore/src/tests/proton/attribute/attribute_test.cpp @@ -445,7 +445,7 @@ TEST_F("require that attribute writer handles update", Fixture) schema.addAttributeField(Schema::AttributeField("a2", schema::DataType::INT32, CollectionType::SINGLE)); DocBuilder idb(schema); const document::DocumentType &dt(idb.getDocumentType()); - DocumentUpdate upd(dt, DocumentId("doc::1")); + DocumentUpdate upd(*idb.getDocumentTypeRepo(), dt, DocumentId("doc::1")); upd.addUpdate(FieldUpdate(upd.getType().getField("a1")) .addUpdate(ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 5))); upd.addUpdate(FieldUpdate(upd.getType().getField("a2")) @@ -489,7 +489,7 @@ TEST_F("require that attribute writer handles predicate update", Fixture) EXPECT_EQUAL(2u, a1->getNumDocs()); const document::DocumentType &dt(idb.getDocumentType()); - DocumentUpdate upd(dt, DocumentId("doc::1")); + DocumentUpdate upd(*idb.getDocumentTypeRepo(), dt, DocumentId("doc::1")); PredicateFieldValue new_value(builder.feature("foo").value("bar").build()); upd.addUpdate(FieldUpdate(upd.getType().getField("a1")) .addUpdate(AssignValueUpdate(new_value))); @@ -678,7 +678,7 @@ TEST_F("require that attribute writer handles tensor assign update", Fixture) EXPECT_TRUE(tensor->equals(*tensor2)); const document::DocumentType &dt(builder.getDocumentType()); - DocumentUpdate upd(dt, DocumentId("doc::1")); + DocumentUpdate upd(*builder.getDocumentTypeRepo(), dt, DocumentId("doc::1")); auto new_tensor = createTensor({ {{{"x", "8"}, {"y", "9"}}, 11} }, {"x", "y"}); TensorFieldValue new_value; diff --git a/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp b/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp index e774728b41e..a1bce7174bf 100644 --- a/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp +++ b/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp @@ -316,7 +316,7 @@ struct UpdateContext { DocumentUpdate::SP update; BucketId bucketId; UpdateContext(const vespalib::string &docId, DocBuilder &builder) : - update(new DocumentUpdate(builder.getDocumentType(), DocumentId(docId))), + update(new DocumentUpdate(*builder.getDocumentTypeRepo(), builder.getDocumentType(), DocumentId(docId))), bucketId(BucketFactory::getBucketId(update->getId())) { } diff --git a/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp b/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp index a9fa79f513c..111b4047da3 100644 --- a/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp +++ b/searchcore/src/tests/proton/documentdb/feedview/feedview_test.cpp @@ -478,11 +478,11 @@ struct DocumentContext DocumentContext::DocumentContext(const vespalib::string &docId, uint64_t timestamp, DocBuilder &builder) : doc(builder.startDocument(docId).startSummaryField("s1").addStr(docId).endField().endDocument().release()), - upd(new DocumentUpdate(builder.getDocumentType(), doc->getId())), + upd(new DocumentUpdate(*builder.getDocumentTypeRepo(), builder.getDocumentType(), doc->getId())), bid(BucketFactory::getNumBucketBits(), doc->getId().getGlobalId().convertToBucketId().getRawId()), ts(timestamp) {} -DocumentContext::~DocumentContext() {} +DocumentContext::~DocumentContext() = default; struct FeedTokenContext { diff --git a/searchcore/src/tests/proton/feedoperation/feedoperation_test.cpp b/searchcore/src/tests/proton/feedoperation/feedoperation_test.cpp index 9a9d896f2b9..e87e9209a17 100644 --- a/searchcore/src/tests/proton/feedoperation/feedoperation_test.cpp +++ b/searchcore/src/tests/proton/feedoperation/feedoperation_test.cpp @@ -122,7 +122,7 @@ public: } auto makeUpdate() { - auto upd(std::make_shared<DocumentUpdate>(_docType, docId)); + auto upd(std::make_shared<DocumentUpdate>(*_repo, _docType, docId)); upd->addUpdate(FieldUpdate(upd->getType().getField("string")). addUpdate(AssignValueUpdate(StringFieldValue("newval")))); return upd; @@ -136,6 +136,7 @@ public: TEST("require that toString() on derived classes are meaningful") { + DocumentTypeRepo repo; BucketId bucket_id1(42); BucketId bucket_id2(43); BucketId bucket_id3(44); @@ -146,7 +147,7 @@ TEST("require that toString() on derived classes are meaningful") MyStreamHandler stream_handler; DocumentIdT doc_id_limit = 15; DocumentId doc_id("doc:foo:bar"); - DocumentUpdate::SP update(new DocumentUpdate(*DataType::DOCUMENT, doc_id)); + DocumentUpdate::SP update(new DocumentUpdate(repo, *DataType::DOCUMENT, doc_id)); EXPECT_EQUAL("DeleteBucket(BucketId(0x0000000000000000), serialNum=0)", DeleteBucketOperation().toString()); diff --git a/searchcore/src/tests/proton/persistenceengine/persistenceengine_test.cpp b/searchcore/src/tests/proton/persistenceengine/persistenceengine_test.cpp index 73580416e65..7f065d0cc15 100644 --- a/searchcore/src/tests/proton/persistenceengine/persistenceengine_test.cpp +++ b/searchcore/src/tests/proton/persistenceengine/persistenceengine_test.cpp @@ -67,7 +67,9 @@ createDoc(const DocumentType &docType, const DocumentId &docId) document::DocumentUpdate::SP createUpd(const DocumentType& docType, const DocumentId &docId) { - return document::DocumentUpdate::SP(new document::DocumentUpdate(docType, docId)); + static std::vector<std::unique_ptr<document::DocumentTypeRepo>> repoList; + repoList.emplace_back(std::make_unique<document::DocumentTypeRepo>(docType)); + return std::make_shared<document::DocumentUpdate>(*repoList.back(), docType, docId); } storage::spi::ClusterState diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp index d31f1faec77..824909d0431 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp @@ -51,12 +51,11 @@ UpdateOperation::serializeUpdate(vespalib::nbostream &os) const } void -UpdateOperation::deserializeUpdate(vespalib::nbostream &is, const document::DocumentTypeRepo &repo) +UpdateOperation::deserializeUpdate(vespalib::nbostream && is, const document::DocumentTypeRepo &repo) { - document::ByteBuffer buf(is.peek(), is.size()); - DocumentUpdate::UP update = (getType() == UPDATE_42) ? DocumentUpdate::create42(repo, buf) : DocumentUpdate::createHEAD(repo, buf); - is.adjustReadPos(buf.getPos()); - _upd = std::move(update); + _upd = (getType() == UPDATE_42) + ? DocumentUpdate::create42(repo, is) + : DocumentUpdate::createHEAD(repo, std::move(is)); } void @@ -73,7 +72,7 @@ UpdateOperation::deserialize(vespalib::nbostream &is, const DocumentTypeRepo &re { DocumentOperation::deserialize(is, repo); try { - deserializeUpdate(is, repo); + deserializeUpdate(std::move(is), repo); } catch (document::DocumentTypeNotFoundException &e) { LOG(warning, "Failed deserialize update operation using unknown document type '%s'", e.getDocumentTypeName().c_str()); @@ -87,14 +86,14 @@ UpdateOperation::deserializeUpdate(const DocumentTypeRepo &repo) { vespalib::nbostream stream; serializeUpdate(stream); - deserializeUpdate(stream, repo); + deserializeUpdate(std::move(stream), repo); } -vespalib::string UpdateOperation::toString() const { +vespalib::string +UpdateOperation::toString() const { return make_string("%s(%s, %s)", ((getType() == FeedOperation::UPDATE_42) ? "Update42" : "Update"), - _upd.get() ? - _upd->getId().getScheme().toString().c_str() : "NULL", + _upd.get() ? _upd->getId().getScheme().toString().c_str() : "NULL", docArgsToString().c_str()); } diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h index 99dcbfbce6c..554778728f0 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h @@ -19,7 +19,7 @@ private: const storage::spi::Timestamp ×tamp, const DocumentUpdateSP &upd); void serializeUpdate(vespalib::nbostream &os) const; - void deserializeUpdate(vespalib::nbostream &is, const document::DocumentTypeRepo &repo); + void deserializeUpdate(vespalib::nbostream && is, const document::DocumentTypeRepo &repo); public: UpdateOperation(); UpdateOperation(Type type); diff --git a/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.cpp b/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.cpp index bab3494ca5c..f774c953af4 100644 --- a/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.cpp +++ b/searchcore/src/vespa/searchcore/proton/persistenceengine/persistenceengine.cpp @@ -377,6 +377,7 @@ PersistenceEngine::update(const Bucket& b, Timestamp t, const DocumentUpdate::SP upd->getId().toString().c_str(), state.message().c_str())); } } + upd->eagerDeserialize(); std::shared_lock<std::shared_timed_mutex> rguard(_rwMutex); DocTypeName docType(upd->getType()); LOG(spam, "update(%s, %" PRIu64 ", (\"%s\", \"%s\"), createIfNonExistent='%s')", diff --git a/storage/src/tests/bucketdb/bucketmanagertest.cpp b/storage/src/tests/bucketdb/bucketmanagertest.cpp index d12e6b90b2a..829a080ad01 100644 --- a/storage/src/tests/bucketdb/bucketmanagertest.cpp +++ b/storage/src/tests/bucketdb/bucketmanagertest.cpp @@ -723,6 +723,7 @@ public: auto createUpdateCommand(const document::BucketId& bucket) const { auto update = std::make_shared<document::DocumentUpdate>( + _self._node->getTestDocMan().getTypeRepo(), *_self._node->getTestDocMan().getTypeRepo() .getDocumentType("testdoctype1"), document::DocumentId("id:foo:testdoctype1::bar2")); diff --git a/storage/src/tests/distributor/externaloperationhandlertest.cpp b/storage/src/tests/distributor/externaloperationhandlertest.cpp index 81b0293b0c0..54aca78d13d 100644 --- a/storage/src/tests/distributor/externaloperationhandlertest.cpp +++ b/storage/src/tests/distributor/externaloperationhandlertest.cpp @@ -200,6 +200,7 @@ std::shared_ptr<api::UpdateCommand> ExternalOperationHandlerTest::makeUpdateComm const vespalib::string& doc_type, const vespalib::string& id) const { auto update = std::make_shared<document::DocumentUpdate>( + _testDocMan.getTypeRepo(), *_testDocMan.getTypeRepo().getDocumentType(doc_type), document::DocumentId(id)); return std::make_shared<api::UpdateCommand>( diff --git a/storage/src/tests/distributor/twophaseupdateoperationtest.cpp b/storage/src/tests/distributor/twophaseupdateoperationtest.cpp index 28602124045..ea2cc00c642 100644 --- a/storage/src/tests/distributor/twophaseupdateoperationtest.cpp +++ b/storage/src/tests/distributor/twophaseupdateoperationtest.cpp @@ -294,7 +294,7 @@ TwoPhaseUpdateOperationTest::sendUpdate(const std::string& bucketState, document::DocumentUpdate::SP update; if (!options._withError) { update = std::make_shared<document::DocumentUpdate>( - *_doc_type, + *_repo, *_doc_type, document::DocumentId(document::DocIdString("test", "test"))); document::FieldUpdate fup(_doc_type->getField("headerval")); fup.addUpdate(ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 10)); @@ -304,7 +304,7 @@ TwoPhaseUpdateOperationTest::sendUpdate(const std::string& bucketState, // part of the Get. Just a sneaky way to force an eval error. auto* badDocType = _repo->getDocumentType("testdoctype2"); update = std::make_shared<document::DocumentUpdate>( - *badDocType, + *_repo, *badDocType, document::DocumentId(document::DocIdString("test", "test"))); document::FieldUpdate fup(badDocType->getField("onlyinchild")); fup.addUpdate(ArithmeticValueUpdate(ArithmeticValueUpdate::Add, 10)); diff --git a/storage/src/tests/distributor/updateoperationtest.cpp b/storage/src/tests/distributor/updateoperationtest.cpp index 92474728957..9ce862f5db8 100644 --- a/storage/src/tests/distributor/updateoperationtest.cpp +++ b/storage/src/tests/distributor/updateoperationtest.cpp @@ -75,8 +75,7 @@ std::shared_ptr<UpdateOperation> UpdateOperation_Test::sendUpdate(const std::string& bucketState) { document::DocumentUpdate::SP update( - new document::DocumentUpdate( - *_html_type, + new document::DocumentUpdate(*_repo, *_html_type, document::DocumentId(document::DocIdString("test", "test")))); _bId = getExternalOperationHandler().getBucketId(update->getId()); diff --git a/storage/src/tests/persistence/filestorage/filestormanagertest.cpp b/storage/src/tests/persistence/filestorage/filestormanagertest.cpp index 838df87662f..369e820f987 100644 --- a/storage/src/tests/persistence/filestorage/filestormanagertest.cpp +++ b/storage/src/tests/persistence/filestorage/filestormanagertest.cpp @@ -2725,6 +2725,7 @@ void FileStorManagerTest::update_command_size_is_added_to_metric() { document::BucketId bucket(16, 4000); createBucket(bucket, 0); auto update = std::make_shared<document::DocumentUpdate>( + _node->getTestDocMan().getTypeRepo(), _node->getTestDocMan().createRandomDocument()->getType(), document::DocumentId("id:foo:testdoctype1::bar")); auto cmd = std::make_shared<api::UpdateCommand>( diff --git a/storage/src/tests/persistence/persistencetestutils.cpp b/storage/src/tests/persistence/persistencetestutils.cpp index f15921e447d..368eae104e8 100644 --- a/storage/src/tests/persistence/persistencetestutils.cpp +++ b/storage/src/tests/persistence/persistencetestutils.cpp @@ -223,16 +223,11 @@ PersistenceTestUtils::doGetOnDisk( } document::DocumentUpdate::SP -PersistenceTestUtils::createBodyUpdate( - const document::DocumentId& docId, - const document::FieldValue& updateValue) +PersistenceTestUtils::createBodyUpdate(const document::DocumentId& docId, const document::FieldValue& updateValue) { - const DocumentType* docType(_env->_component.getTypeRepo() - ->getDocumentType("testdoctype1")); - document::DocumentUpdate::SP update( - new document::DocumentUpdate(*docType, docId)); - std::shared_ptr<document::AssignValueUpdate> assignUpdate( - new document::AssignValueUpdate(updateValue)); + const DocumentType* docType(_env->_component.getTypeRepo()->getDocumentType("testdoctype1")); + document::DocumentUpdate::SP update(new document::DocumentUpdate(*_env->_component.getTypeRepo(), *docType, docId)); + std::shared_ptr<document::AssignValueUpdate> assignUpdate(new document::AssignValueUpdate(updateValue)); document::FieldUpdate fieldUpdate(docType->getField("content")); fieldUpdate.addUpdate(*assignUpdate); update->addUpdate(fieldUpdate); @@ -240,16 +235,11 @@ PersistenceTestUtils::createBodyUpdate( } document::DocumentUpdate::SP -PersistenceTestUtils::createHeaderUpdate( - const document::DocumentId& docId, - const document::FieldValue& updateValue) +PersistenceTestUtils::createHeaderUpdate(const document::DocumentId& docId, const document::FieldValue& updateValue) { - const DocumentType* docType(_env->_component.getTypeRepo() - ->getDocumentType("testdoctype1")); - document::DocumentUpdate::SP update( - new document::DocumentUpdate(*docType, docId)); - std::shared_ptr<document::AssignValueUpdate> assignUpdate( - new document::AssignValueUpdate(updateValue)); + const DocumentType* docType(_env->_component.getTypeRepo()->getDocumentType("testdoctype1")); + document::DocumentUpdate::SP update(new document::DocumentUpdate(*_env->_component.getTypeRepo(), *docType, docId)); + std::shared_ptr<document::AssignValueUpdate> assignUpdate(new document::AssignValueUpdate(updateValue)); document::FieldUpdate fieldUpdate(docType->getField("headerval")); fieldUpdate.addUpdate(*assignUpdate); update->addUpdate(fieldUpdate); diff --git a/storage/src/tests/persistence/testandsettest.cpp b/storage/src/tests/persistence/testandsettest.cpp index c729df1e7eb..686e10ba5ef 100644 --- a/storage/src/tests/persistence/testandsettest.cpp +++ b/storage/src/tests/persistence/testandsettest.cpp @@ -189,7 +189,7 @@ std::unique_ptr<api::UpdateCommand> TestAndSetTest::conditional_update_test( { putTestDocument(matchingHeader, timestampOne); - auto docUpdate = std::make_shared<document::DocumentUpdate>(testDoc->getType(), testDocId); + auto docUpdate = std::make_shared<document::DocumentUpdate>(_env->_testDocMan.getTypeRepo(), testDoc->getType(), testDocId); auto fieldUpdate = document::FieldUpdate(testDoc->getField("content")); fieldUpdate.addUpdate(document::AssignValueUpdate(NEW_CONTENT)); docUpdate->addUpdate(fieldUpdate); diff --git a/storage/src/tests/storageserver/changedbucketownershiphandlertest.cpp b/storage/src/tests/storageserver/changedbucketownershiphandlertest.cpp index 7df598bed97..98ad8761736 100644 --- a/storage/src/tests/storageserver/changedbucketownershiphandlertest.cpp +++ b/storage/src/tests/storageserver/changedbucketownershiphandlertest.cpp @@ -597,25 +597,19 @@ ChangedBucketOwnershipHandlerTest::testAbortOutdatedPutOperation() void ChangedBucketOwnershipHandlerTest::testAbortOutdatedUpdateCommand() { - const document::DocumentType* docType(_testDocRepo.getTypeRepo() - .getDocumentType("testdoctype1")); + const document::DocumentType* docType(_testDocRepo.getTypeRepo().getDocumentType("testdoctype1")); document::DocumentId docId("id:foo:testdoctype1::bar"); - document::DocumentUpdate::SP update( - std::make_shared<document::DocumentUpdate>(*docType, docId)); - CPPUNIT_ASSERT(changeAbortsMessage<api::UpdateCommand>( - getBucketToAbort(), update, api::Timestamp(1234))); - CPPUNIT_ASSERT(!changeAbortsMessage<api::UpdateCommand>( - getBucketToAllow(), update, api::Timestamp(1234))); + auto update(std::make_shared<document::DocumentUpdate>(_testDocRepo.getTypeRepo(), *docType, docId)); + CPPUNIT_ASSERT(changeAbortsMessage<api::UpdateCommand>(getBucketToAbort(), update, api::Timestamp(1234))); + CPPUNIT_ASSERT(!changeAbortsMessage<api::UpdateCommand>(getBucketToAllow(), update, api::Timestamp(1234))); } void ChangedBucketOwnershipHandlerTest::testAbortOutdatedRemoveCommand() { document::DocumentId docId("id:foo:testdoctype1::bar"); - CPPUNIT_ASSERT(changeAbortsMessage<api::RemoveCommand>( - getBucketToAbort(), docId, api::Timestamp(1234))); - CPPUNIT_ASSERT(!changeAbortsMessage<api::RemoveCommand>( - getBucketToAllow(), docId, api::Timestamp(1234))); + CPPUNIT_ASSERT(changeAbortsMessage<api::RemoveCommand>(getBucketToAbort(), docId, api::Timestamp(1234))); + CPPUNIT_ASSERT(!changeAbortsMessage<api::RemoveCommand>(getBucketToAllow(), docId, api::Timestamp(1234))); } void diff --git a/storage/src/tests/storageserver/documentapiconvertertest.cpp b/storage/src/tests/storageserver/documentapiconvertertest.cpp index 695ae17c5d4..40d561bd589 100644 --- a/storage/src/tests/storageserver/documentapiconvertertest.cpp +++ b/storage/src/tests/storageserver/documentapiconvertertest.cpp @@ -181,7 +181,7 @@ void DocumentApiConverterTest::testForwardedPut() void DocumentApiConverterTest::testUpdate() { - auto update = std::make_shared<document::DocumentUpdate>(_html_type, defaultDocId); + auto update = std::make_shared<document::DocumentUpdate>(*_repo, _html_type, defaultDocId); documentapi::UpdateDocumentMessage updateMsg(update); updateMsg.setOldTimestamp(1234); updateMsg.setNewTimestamp(5678); @@ -327,19 +327,19 @@ DocumentApiConverterTest::testBatchDocumentUpdate() { document::DocumentId docId(document::UserDocIdString("userdoc:test:1234:test1")); - auto update = std::make_shared<document::DocumentUpdate>(_html_type, docId); + auto update = std::make_shared<document::DocumentUpdate>(*_repo, _html_type, docId); updates.push_back(update); } { document::DocumentId docId(document::UserDocIdString("userdoc:test:1234:test2")); - auto update = std::make_shared<document::DocumentUpdate>(_html_type, docId); + auto update = std::make_shared<document::DocumentUpdate>(*_repo, _html_type, docId); updates.push_back(update); } { document::DocumentId docId(document::UserDocIdString("userdoc:test:1234:test3")); - auto update = std::make_shared<document::DocumentUpdate>(_html_type, docId); + auto update = std::make_shared<document::DocumentUpdate>(*_repo, _html_type, docId); updates.push_back(update); } diff --git a/storageapi/src/tests/mbusprot/storageprotocoltest.cpp b/storageapi/src/tests/mbusprot/storageprotocoltest.cpp index a809d80e0f5..cfc69bcde45 100644 --- a/storageapi/src/tests/mbusprot/storageprotocoltest.cpp +++ b/storageapi/src/tests/mbusprot/storageprotocoltest.cpp @@ -294,7 +294,7 @@ void StorageProtocolTest::testUpdate51() { ScopedName test("testUpdate51"); - document::DocumentUpdate::SP update(new document::DocumentUpdate(*_testDoc->getDataType(), _testDoc->getId())); + document::DocumentUpdate::SP update(new document::DocumentUpdate(_docMan.getTypeRepo(), *_testDoc->getDataType(), _testDoc->getId())); std::shared_ptr<document::AssignValueUpdate> assignUpdate(new document::AssignValueUpdate(document::IntFieldValue(17))); document::FieldUpdate fieldUpdate(_testDoc->getField("headerval")); fieldUpdate.addUpdate(*assignUpdate); @@ -912,7 +912,7 @@ StorageProtocolTest::testUpdateCommand52() { ScopedName test("testUpdateCommand52"); - document::DocumentUpdate::SP update(new document::DocumentUpdate(*_testDoc->getDataType(), _testDoc->getId())); + document::DocumentUpdate::SP update(new document::DocumentUpdate(_docMan.getTypeRepo(), *_testDoc->getDataType(), _testDoc->getId())); UpdateCommand::SP cmd(new UpdateCommand(_bucket, update, 14)); cmd->setCondition(TestAndSetCondition(CONDITION_STRING)); diff --git a/storageapi/src/vespa/storageapi/mbusprot/protocolserialization5_0.cpp b/storageapi/src/vespa/storageapi/mbusprot/protocolserialization5_0.cpp index 44050264484..47b77af74a5 100644 --- a/storageapi/src/vespa/storageapi/mbusprot/protocolserialization5_0.cpp +++ b/storageapi/src/vespa/storageapi/mbusprot/protocolserialization5_0.cpp @@ -228,9 +228,8 @@ ProtocolSerialization5_0::onDecodeUpdateCommand(BBuf& buf) const uint32_t size = SH::getInt(buf); if (size != 0) { - document::ByteBuffer bbuf(buf.getBufferAtPos(), size); + update = document::DocumentUpdate::createHEAD(getTypeRepo(), vespalib::nbostream(buf.getBufferAtPos(), size)); buf.incPos(size); - update = document::DocumentUpdate::createHEAD(getTypeRepo(), bbuf); } document::Bucket bucket = getBucket(buf); |