]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
ixfrdist: Reduce memory usage during zone retrieval
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 27 Aug 2018 13:33:24 +0000 (15:33 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 28 Aug 2018 09:01:03 +0000 (11:01 +0200)
pdns/ixfrdist.cc
pdns/ixfrutils.cc

index 383665cd4d0a1be0232c6591b87b4ae4de72c921..779cb8608a4a9375efad3548739a570c63d74030 100644 (file)
@@ -297,12 +297,12 @@ void updateThread(const string& workdir, const uint16_t& keep, const uint16_t& a
 
       // The *new* SOA
       shared_ptr<SOARecordContent> soa;
+      records_t records;
       try {
         AXFRRetriever axfr(master, domain, tt, &local);
         unsigned int nrecords=0;
         Resolver::res_t nop;
         vector<DNSRecord> chunk;
-        records_t records;
         time_t t_start = time(nullptr);
         time_t axfr_now = time(nullptr);
         while(axfr.getChunk(nop, &chunk, (axfr_now - t_start + axfrTimeout))) {
@@ -326,27 +326,39 @@ void updateThread(const string& workdir, const uint16_t& keep, const uint16_t& a
           continue;
         }
         g_log<<Logger::Notice<<"Retrieved all zone data for "<<domain<<". Received "<<nrecords<<" records."<<endl;
+      } catch (PDNSException &e) {
+        g_log<<Logger::Warning<<"Could not retrieve AXFR for '"<<domain<<"': "<<e.reason<<endl;
+      } catch (runtime_error &e) {
+        g_log<<Logger::Warning<<"Could not retrieve AXFR for zone '"<<domain<<"': "<<e.what()<<endl;
+      }
+
+      try {
+
         writeZoneToDisk(records, domain, dir);
         g_log<<Logger::Notice<<"Wrote zonedata for "<<domain<<" with serial "<<soa->d_st.serial<<" to "<<dir<<endl;
+
         {
           std::lock_guard<std::mutex> guard(g_soas_mutex);
           ixfrdiff_t diff;
           if (!g_soas[domain].latestAXFR.empty()) {
             makeIXFRDiff(g_soas[domain].latestAXFR, records, diff, g_soas[domain].soa, soa);
-            g_soas[domain].ixfrDiffs.push_back(diff);
+            g_soas[domain].ixfrDiffs.push_back(std::move(diff));
           }
+
           // Clean up the diffs
           while (g_soas[domain].ixfrDiffs.size() > keep) {
             g_soas[domain].ixfrDiffs.erase(g_soas[domain].ixfrDiffs.begin());
           }
-          g_soas[domain].latestAXFR = records;
+
+          g_soas[domain].latestAXFR = std::move(records);
           g_soas[domain].soa = soa;
         }
       } catch (PDNSException &e) {
-        g_log<<Logger::Warning<<"Could not retrieve AXFR for '"<<domain<<"': "<<e.reason<<endl;
+        g_log<<Logger::Warning<<"Could not save zone '"<<domain<<"' to disk: "<<e.reason<<endl;
       } catch (runtime_error &e) {
         g_log<<Logger::Warning<<"Could not save zone '"<<domain<<"' to disk: "<<e.what()<<endl;
       }
+
       // Now clean up the directory
       cleanUpDomain(domain, keep, workdir);
     } /* for (const auto &domain : domains) */
index 04c832451d8cb0b36034192730cd7c65740afbba..c7757042baa263aff47e6754d009166854492467 100644 (file)
@@ -105,6 +105,17 @@ uint32_t getSerialFromRecords(const records_t& records, DNSRecord& soaret)
   return 0;
 }
 
+static void writeRecords(FILE* fp, const records_t& records)
+{
+  for(const auto& r: records) {
+    fprintf(fp, "%s\t%" PRIu32 "\tIN\t%s\t%s\n",
+            r.d_name.isRoot() ? "@" :  r.d_name.toStringNoDot().c_str(),
+            r.d_ttl,
+            DNSRecordContent::NumberToType(r.d_type).c_str(),
+            r.d_content->getZoneRepresentation().c_str());
+  }
+}
+
 void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::string& directory)
 {
   DNSRecord soa;
@@ -117,15 +128,11 @@ void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::s
   records_t soarecord;
   soarecord.insert(soa);
   fprintf(fp, "$ORIGIN %s\n", zone.toString().c_str());
-  for(const auto& outer : {soarecord, records, soarecord} ) {
-    for(const auto& r: outer) {
-      fprintf(fp, "%s\t%" PRIu32 "\tIN\t%s\t%s\n",
-          r.d_name.isRoot() ? "@" :  r.d_name.toStringNoDot().c_str(),
-          r.d_ttl,
-          DNSRecordContent::NumberToType(r.d_type).c_str(),
-          r.d_content->getZoneRepresentation().c_str());
-    }
-  }
+
+  writeRecords(fp, soarecord);
+  writeRecords(fp, records);
+  writeRecords(fp, soarecord);
+
   fclose(fp);
   rename( (fname+".partial").c_str(), fname.c_str());
 }