]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
auth lmdb: add 'index check domains' and 'index refresh domains <ID>' backend-cmds
authorPeter van Dijk <peter.van.dijk@powerdns.com>
Tue, 4 Jul 2023 18:25:09 +0000 (20:25 +0200)
committerPeter van Dijk <peter.van.dijk@powerdns.com>
Thu, 6 Jul 2023 12:16:38 +0000 (14:16 +0200)
modules/lmdbbackend/lmdbbackend.cc

index ada437db984bb181169950626907fde96cd609f4..506cd4783dd522176f7af23dfbb7acaabd023580 100644 (file)
@@ -2620,17 +2620,107 @@ bool LMDBBackend::getTSIGKeys(std::vector<struct TSIGKey>& keys)
 
 string LMDBBackend::directBackendCmd(const string& query)
 {
-  if (query == "info") {
-    ostringstream ret;
+  ostringstream ret, usage;
 
+  usage << "info                               show some information about the database" << endl;
+  usage << "index check domains                check zone<>ID indexes" << endl;
+  usage << "index refresh domains <ID>         refresh index for zone with this ID" << endl;
+
+  vector<string> argv;
+  stringtok(argv, query);
+
+  if (argv.empty()) {
+    return usage.str();
+  }
+
+  string& cmd = argv[0];
+
+  if (cmd == "help") {
+    return usage.str();
+  }
+
+  if (cmd == "info") {
     ret << "shards: " << s_shards << endl;
     ret << "schemaversion: " << SCHEMAVERSION << endl;
 
     return ret.str();
   }
-  else {
-    return "unknown lmdbbackend command\n";
+
+  if (cmd == "index") {
+    if (argv.size() < 2) {
+      return "need an index subcommand\n";
+    }
+
+    string& subcmd = argv[1];
+
+    if (subcmd == "check") {
+      if (argv.size() < 3) {
+        return "need an index name\n";
+      }
+
+      if (argv[2] != "domains") {
+        return "can only check the domains index\n";
+      }
+
+      auto txn = d_tdomains->getROTransaction();
+
+      for (auto iter = txn.begin(); iter != txn.end(); ++iter) {
+        DomainInfo di = *iter;
+
+        auto id = iter.getID();
+
+        LMDBIDvec ids;
+        txn.get_multi<0>(di.zone, ids);
+
+        if (ids.size() != 1) {
+          ret << "ID->zone index has " << id << "->" << di.zone << ", ";
+
+          if (ids.empty()) {
+            ret << "zone->ID index has no entry for " << di.zone << endl;
+            ret << "  suggested remedy: index refresh domains " << id << endl;
+          }
+          else {
+            // ids.size() > 1
+            ret << "zone->ID index has multiple entries for " << di.zone << ": ";
+            for (auto id_ : ids) {
+              ret << id_ << " ";
+            }
+            ret << endl;
+          }
+        }
+      }
+      return ret.str();
+    }
+    if (subcmd == "refresh") {
+      // index refresh domains 12345
+      if (argv.size() < 4) {
+        return "usage: index refresh domains <ID>\n";
+      }
+
+      if (argv[2] != "domains") {
+        return "can only refresh in the domains index\n";
+      }
+
+      uint32_t id = 0;
+
+      try {
+        id = pdns::checked_stoi<uint32_t>(argv[3]);
+      }
+      catch (const std::out_of_range& e) {
+        return "ID out of range\n";
+      }
+
+      if (genChangeDomain(id, [](DomainInfo& /* di */) {})) {
+        ret << "refreshed" << endl;
+      }
+      else {
+        ret << "failed" << endl;
+      }
+      return ret.str();
+    }
   }
+
+  return "unknown lmdbbackend command\n";
 }
 
 class LMDBFactory : public BackendFactory