auto txn = d_ttsig->getROTransaction();
keys.clear();
- for (auto iter = txn.begin(); iter != txn.end(); ++iter) {
- keys.push_back(*iter);
+ // In a perfect world, we would simply iterate over txn and add every
+ // item to the returned vector:
+ // for (auto iter = txn.begin(); iter != txn.end(); ++iter) {
+ // keys.push_back(*iter);
+ // }
+ // But databases converted from older (< 5) schemas _may_ have multiple
+ // entries for the same TSIG key name and algorithm, something which is not
+ // allowed in the v5 database schema. These extra entries will not be found
+ // by get_multi<> during regular operations, and would only appear in the
+ // results of this method.
+ // In order to prevent this, we first only gather the list of key names, and
+ // in a second step, query for them using a similar logic as getTSIGKey().
+ // Unfortunately, there does not seem to be a way to know if the database had
+ // been created using the v5 schema (not converted), in which case we could
+ // use the above, simpler logic.
+ std::unordered_set<DNSName> keynames;
+ for (const auto& iter : txn) {
+ keynames.insert(iter.name);
+ }
+ for (const auto& iter : keynames) {
+ LmdbIdVec ids;
+ txn.get_multi<0>(iter, ids);
+ for (auto key_id : ids) {
+ TSIGKey key;
+ if (txn.get(key_id, key)) {
+ keys.push_back(key);
+ }
+ }
}
return true;
}