summaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorTor Egge <tegge@oath.com>2017-08-14 21:23:42 +0000
committerTor Egge <tegge@oath.com>2017-08-14 21:23:42 +0000
commita1682ec2fb64df93939d7131bedb08657ca2b74d (patch)
tree7e86c86b9f39c0b58b4129b168746c82556dee42 /searchlib
parent7448bdbd43e43d2b8b355b57da2373952e1665f0 (diff)
Recover from temporary glitch in reverse mapping.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp40
-rw-r--r--searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp2
2 files changed, 41 insertions, 1 deletions
diff --git a/searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp b/searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp
index 73e27ca4f7d..337cdcc30e8 100644
--- a/searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp
+++ b/searchlib/src/tests/attribute/reference_attribute/reference_attribute_test.cpp
@@ -41,6 +41,17 @@ struct MyGidToLidMapperFactory : public search::attribute::test::MockGidToLidMap
_map.insert({toGid(doc1), 10});
_map.insert({toGid(doc2), 17});
}
+
+ void add(vespalib::stringref docId, uint32_t lid) {
+ auto insres = _map.insert({ toGid(docId), lid });
+ if (!insres.second) {
+ insres.first->second = lid;
+ }
+ }
+
+ void remove(vespalib::stringref docId) {
+ _map.erase(toGid(docId));
+ }
};
class LidCollector
@@ -371,4 +382,33 @@ TEST_F("Require that notifyGidToLidChange changes reverse mapping", Fixture)
TEST_DO(f.assertLids(11, { }));
}
+TEST_F("Require that reverse mapping recovers from temporary out of order glitch", Fixture)
+{
+ auto factory = std::make_shared<MyGidToLidMapperFactory>();
+ f._attr->setGidToLidMapperFactory(factory);
+ f.ensureDocIdLimit(4);
+ f.set(1, toGid(doc1));
+ f.set(2, toGid(doc2));
+ /*
+ * Changes in gid to lid mapping can be visible via gid to lid
+ * mapper before notifications arrive. If a lid is reused in the
+ * referenced document meta store then multiple entries in
+ * reference store might temporarily map to the same referenced
+ * lid.
+ */
+ factory->remove(doc1); // remove referenced document
+ factory->add(doc3, 10); // reuse lid for new referenced document
+ f.set(3, toGid(doc3));
+ TEST_DO(f.assertRefLid(1, 10));
+ TEST_DO(f.assertRefLid(2, 17));
+ TEST_DO(f.assertRefLid(3, 10));
+ // Notify reference attribute about gid to lid mapping changes
+ f.notifyGidToLidChange(toGid(doc1), 0);
+ f.notifyGidToLidChange(toGid(doc3), 10);
+ TEST_DO(f.assertRefLid(1, 0));
+ TEST_DO(f.assertRefLid(2, 17));
+ TEST_DO(f.assertRefLid(3, 10));
+ TEST_DO(f.assertLids(10, { 3 }));
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp b/searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp
index 17afa6f9a2d..5a088fd1d64 100644
--- a/searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/reference_attribute.cpp
@@ -366,8 +366,8 @@ ReferenceAttribute::notifyGidToLidChange(const GlobalId &gid, DocId referencedLi
_reverseMappingIndices[oldReferencedLid] = EntryRef();
}
entry.setLid(referencedLid);
- syncReverseMappingIndices(entry);
}
+ syncReverseMappingIndices(entry);
commit();
}
}