Hi Peter,

On Thu, Oct 13, 2011 at 12:56 PM, Peter van Dijk
<[email protected]> wrote:
> Hello Zsolt,
>
> On Oct 1, 2011, at 22:03 , Zsolt Dollenstein wrote:
>
>> I have recently started using powerdns (props for a great piece of
>> software!), however I bumped into what looks like issue #301 on your
>> bugtracker (http://wiki.powerdns.com/trac/ticket/301). It has two
>> patches attached to it but it looks like they have never been merged
>> in. Are there any problems with them? If so, I'm willing to rewrite &
>> test them so they can be included in future versions.
>
> I have looked at both options in the ticket:
> 1. add a change_date to the query and do a minor patch
> 2. add  a max(..) query to getSOA
>
> The first option would break existing setups if they have custom queries. 
> This is of course a matter of documentation but I try to be careful in 
> changing behaviour.
>
> The second option will not break existing setups (but if someone has a custom 
> database schema, he still won't get auto serial with it - which is fine). 
> However, the verbatim copying of code from dnsbackend to gsqlbackend looks a 
> bit verbose.
>
> If you could look into making sure the second patch is not a dumb verbatim 
> copy of code from dnsbackend, I'd be happy to consider it.
>
> My apologies for taking so long to reply.

I restructured the second patch and attached it (it's against HEAD).
Let me know what you think.

Thanks,
Zsolt
Index: pdns/dnsbackend.hh
===================================================================
--- pdns/dnsbackend.hh	(revision 2283)
+++ pdns/dnsbackend.hh	(working copy)
@@ -119,6 +119,9 @@
   //! fills the soadata struct with the SOA details. Returns false if there is no SOA.
   virtual bool getSOA(const string &name, SOAData &soadata, DNSPacket *p=0);
 
+  //! Calculates a SOA serial for the zone and stores it in the third argument.
+  virtual bool calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial);
+
   virtual bool getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta) { return false; }
   virtual bool setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta) {return false;}
   virtual bool getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys) { return false;}
Index: pdns/dnsbackend.cc
===================================================================
--- pdns/dnsbackend.cc	(revision 2283)
+++ pdns/dnsbackend.cc	(working copy)
@@ -234,24 +234,14 @@
   if(!sd.serial) { // magic time!
     DLOG(L<<Logger::Warning<<"Doing soa serialnumber autocalculation for "<<rr.qname<<endl);
 
-    // we do this by listing the domain and taking the maximum last modified timestamp
-
-    DNSResourceRecord i;
-    time_t newest=0;
-
-    if(!(this->list(domain, sd.domain_id))) {
-      DLOG(L<<Logger::Warning<<"Backend error trying to determine magic serial number of zone '"<<domain<<"'"<<endl);
-      return false;
+    time_t serial;
+    if (calculateSOASerial(domain, sd, serial)) {
+      sd.serial = serial;
+      DLOG(L<<"autocalculated soa serialnumber for "<<rr.qname<<" is "<<newest<<endl);
+    } else {
+      DLOG(L<<"soa serialnumber calculation failed for "<<rr.qname<<endl);
     }
-  
-    while(this->get(i)) {
-      if(i.last_modified>newest)
-        newest=i.last_modified;
-    }
 
-    sd.serial=newest; // +arg().asNum("soa-serial-offset");
-    DLOG(L<<"autocalculated soa serialnumber for "<<rr.qname<<" is "<<newest<<endl);
-
   }
   sd.db=this;
   return true;
@@ -270,3 +260,36 @@
   after=dotConcat(labelReverse(after), zonename);
   return ret;
 }
+
+/**
+ * Calculates a SOA serial for the zone and stores it in the third
+ * argument. Returns false if calculation is not possible for some
+ * reason (in this case, the third argument is not inspected). If it
+ * returns true, the value returned in the third argument will be set
+ * as the SOA serial.
+ *
+ * \param domain The name of the domain
+ * \param sd Information about the SOA record already available
+ * \param serial Output parameter. Only inspected when we return true
+ */
+bool DNSBackend::calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial)
+{
+    // we do this by listing the domain and taking the maximum last modified timestamp
+
+    DNSResourceRecord i;
+    time_t newest=0;
+
+    if(!(this->list(domain, sd.domain_id))) {
+      DLOG(L<<Logger::Warning<<"Backend error trying to determine magic serial number of zone '"<<domain<<"'"<<endl);
+      return false;
+    }
+  
+    while(this->get(i)) {
+      if(i.last_modified>newest)
+        newest=i.last_modified;
+    }
+
+    serial=newest; // +arg().asNum("soa-serial-offset");
+
+    return true;
+}
Index: pdns/backends/gsql/gsqlbackend.cc
===================================================================
--- pdns/backends/gsql/gsqlbackend.cc	(revision 2283)
+++ pdns/backends/gsql/gsqlbackend.cc	(working copy)
@@ -267,6 +267,7 @@
   d_InsertRecordQuery=getArg("insert-record-query"+authswitch);
   d_UpdateSerialOfZoneQuery=getArg("update-serial-query");
   d_UpdateLastCheckofZoneQuery=getArg("update-lastcheck-query");
+  d_ZoneLastChangeQuery=getArg("zone-lastchange-query");
   d_InfoOfAllMasterDomainsQuery=getArg("info-all-master-query");
   d_DeleteZoneQuery=getArg("delete-zone-query");
   d_CheckACLQuery=getArg("check-acl-query");
@@ -776,3 +777,31 @@
   return true;
 }
 
+bool GSQLBackend::calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial)
+{
+  if (d_ZoneLastChangeQuery.empty()) {
+    // query not set => fall back to default impl
+    return DNSBackend::calculateSOASerial(domain, sd, serial);
+  }
+  
+  char output[1024];
+  
+  snprintf(output, sizeof(output)-1,
+           d_ZoneLastChangeQuery.c_str(),
+           sd.domain_id);
+
+  try {
+    d_db->doQuery(output, d_result);
+  }
+  catch (const SSqlException& e) {
+    DLOG(L<<"GSQLBackend unable to calculate SOA serial: " << e.txtReason()<<endl);
+    return false;
+  }
+
+  if (not d_result.empty()) {
+    serial = atol(d_result[0][0].c_str());
+    return true;
+  }
+
+  return false;
+}
Index: pdns/backends/gsql/gsqlbackend.hh
===================================================================
--- pdns/backends/gsql/gsqlbackend.hh	(revision 2283)
+++ pdns/backends/gsql/gsqlbackend.hh	(working copy)
@@ -43,6 +43,8 @@
   bool updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth);
   virtual bool updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const std::string& qname, const std::string& ordername, bool auth);
 
+  virtual bool calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial);
+
   int addDomainKey(const string& name, const KeyData& key);
   bool getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys);
   bool getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta);
@@ -81,6 +83,7 @@
   string d_UpdateLastCheckofZoneQuery;
   string d_InfoOfAllMasterDomainsQuery;
   string d_DeleteZoneQuery;		
+  string d_ZoneLastChangeQuery;
   string d_CheckACLQuery;   
   
   string d_beforeOrderQuery;
Index: modules/gmysqlbackend/gmysqlbackend.cc
===================================================================
--- modules/gmysqlbackend/gmysqlbackend.cc	(revision 2283)
+++ modules/gmysqlbackend/gmysqlbackend.cc	(working copy)
@@ -94,6 +94,7 @@
     
     declare(suffix,"update-serial-query","", "update domains set notified_serial=%d where id=%d");
     declare(suffix,"update-lastcheck-query","", "update domains set last_check=%d where id=%d");
+    declare(suffix,"zone-lastchange-query", "", "select max(change_date) from records where domain_id=%d");
     declare(suffix,"info-all-master-query","", "select id,name,master,last_check,notified_serial,type from domains where type='MASTER'");
     declare(suffix,"delete-zone-query","", "delete from records where domain_id=%d");
     declare(suffix,"check-acl-query","", "select value from acls where acl_type='%s' and acl_key='%s'");
Index: modules/gsqlite3backend/gsqlite3backend.cc
===================================================================
--- modules/gsqlite3backend/gsqlite3backend.cc	(revision 2283)
+++ modules/gsqlite3backend/gsqlite3backend.cc	(working copy)
@@ -100,6 +100,7 @@
     
     declare( suffix, "update-serial-query", "", "update domains set notified_serial=%d where id=%d");
     declare( suffix, "update-lastcheck-query", "", "update domains set last_check=%d where id=%d");
+    declare (suffix, "zone-lastchange-query", "", "select max(change_date) from records where domain_id=%d");
     declare( suffix, "info-all-master-query", "", "select id,name,master,last_check,notified_serial,type from domains where type='MASTER'");
     declare( suffix, "delete-zone-query", "", "delete from records where domain_id=%d");
     declare( suffix, "check-acl-query","", "select value from acls where acl_type='%s' and acl_key='%s'");
Index: modules/gpgsqlbackend/gpgsqlbackend.cc
===================================================================
--- modules/gpgsqlbackend/gpgsqlbackend.cc	(revision 2283)
+++ modules/gpgsqlbackend/gpgsqlbackend.cc	(working copy)
@@ -91,6 +91,7 @@
     
     declare(suffix,"update-serial-query","", "update domains set notified_serial=%d where id=%d");
     declare(suffix,"update-lastcheck-query","", "update domains set last_check=%d where id=%d");
+    declare(suffix,"zone-lastchange-query", "", "select max(change_date) from records where domain_id=%d");
     declare(suffix,"info-all-master-query","", "select id,name,master,last_check,notified_serial,type from domains where type='MASTER'");
     declare(suffix,"delete-zone-query","", "delete from records where domain_id=%d");
     declare(suffix,"check-acl-query","", "select value from acls where acl_type='%s' and acl_key='%s'");
_______________________________________________
Pdns-dev mailing list
[email protected]
http://mailman.powerdns.com/mailman/listinfo/pdns-dev

Reply via email to