From: Bert Hubert Date: Sun, 9 Mar 2008 15:31:37 +0000 (+0000) Subject: Norbert sends: X-Git-Tag: rec-3.1.7.1~87 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e830c24957c775ec577388005c604abfa66aa5db;p=thirdparty%2Fpdns.git Norbert sends: Here's an update for the OpenDBX backend: - Fix for SQLite2/3 locking problem on concurrent reads/writes - Fixes compilation on Solaris (u_int vs. uint) - Support for autoserial (needs triggers) git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1154 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/modules/opendbxbackend/odbxbackend.cc b/modules/opendbxbackend/odbxbackend.cc index 10a0e47594..1cfdfde447 100644 --- a/modules/opendbxbackend/odbxbackend.cc +++ b/modules/opendbxbackend/odbxbackend.cc @@ -106,14 +106,29 @@ bool OdbxBackend::getDomainInfo( const string& domain, DomainInfo& di ) di.backend = this; di.serial = 0; - if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) + if( ( tmp = odbx_field_value( m_result, 6 ) ) != NULL ) { - di.id = strtol( tmp, NULL, 10 ); + SOAData sd; + + sd.serial = 0; + fillSOAData( string( tmp, odbx_field_length( m_result, 6 ) ), sd ); + + if( sd.serial == 0 && ( tmp = odbx_field_value( m_result, 5 ) ) != NULL ) + { + sd.serial = strtol( tmp, NULL, 10 ); + } + + di.serial = sd.serial; } - if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) + if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL ) { - di.zone = string( tmp, odbx_field_length( m_result, 1 ) ); + di.last_check = strtol( tmp, NULL, 10 ); + } + + if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) + { + stringtok(di.masters, string( tmp, odbx_field_length( m_result, 3 ) ), ", \t"); } if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) @@ -128,31 +143,80 @@ bool OdbxBackend::getDomainInfo( const string& domain, DomainInfo& di ) } } - if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) + if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) { - string masters = string( tmp, odbx_field_length( m_result, 3 ) ); - stringtok(di.masters, masters, ", \t"); + di.zone = string( tmp, odbx_field_length( m_result, 1 ) ); } - if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL ) + if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) { - di.last_check = strtol( tmp, NULL, 10 ); + di.id = strtol( tmp, NULL, 10 ); } + } + while( getRecord( READ ) ); + } + catch( exception& e ) + { + L.log( m_myname + " getDomainInfo: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } - if( ( tmp = odbx_field_value( m_result, 6 ) ) != NULL ) + return true; +} + + + +bool OdbxBackend::getSOA( const string& domain, SOAData& sd, DNSPacket* p ) +{ + const char* tmp; + + + try + { + DLOG( L.log( m_myname + " getSOA()", Logger::Debug ) ); + + string stmt = getArg( "sql-lookupsoa" ); + string& stmtref = strbind( ":name", escape( toLower( domain ), READ ), stmt ); + + if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } + if( !getRecord( READ ) ) { return false; } + + do + { + sd.serial = 0; + + if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) { - SOAData sd; + fillSOAData( string( tmp, odbx_field_length( m_result, 2 ) ), sd ); + } - sd.serial = 0; - fillSOAData( string( tmp, odbx_field_length( m_result, 6 ) ), sd ); - di.serial = sd.serial; + if( sd.serial == 0 && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) + { + sd.serial = strtol( tmp, NULL, 10 ); } + + if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) + { + sd.domain_id = strtol( tmp, NULL, 10 ); + } + + if( sd.nameserver.empty() ) + { + sd.nameserver = arg()["default-soa-name"]; + } + + if( sd.hostmaster.empty() ) + { + sd.hostmaster = "hostmaster." + domain; + } + + sd.db = this; } while( getRecord( READ ) ); } catch( exception& e ) { - L.log( m_myname + " getDomainInfo: Caught STL exception - " + e.what(), Logger::Error ); + L.log( m_myname + " getSOA: Caught STL exception - " + e.what(), Logger::Error ); return false; } @@ -211,7 +275,7 @@ void OdbxBackend::lookup( const QType& qtype, const string& qname, DNSPacket* dn m_result = NULL; m_qname = qname; - + if( zoneid < 0 ) { if( qtype.getCode() == QType::ANY ) @@ -231,7 +295,7 @@ void OdbxBackend::lookup( const QType& qtype, const string& qname, DNSPacket* dn stmt = getArg( "sql-lookuptypeid" ); stmtref = strbind( ":type", qtype.getName(), stmt ); } - + size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid ); if( len < 0 ) @@ -306,7 +370,7 @@ bool OdbxBackend::get( DNSResourceRecord& rr ) if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL ) { - rr.priority = (u_int16_t) strtoul( tmp, NULL, 10 ); + rr.priority = (uint16_t) strtoul( tmp, NULL, 10 ); } if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL ) @@ -327,7 +391,7 @@ bool OdbxBackend::get( DNSResourceRecord& rr ) } -void OdbxBackend::setFresh( u_int32_t domain_id ) +void OdbxBackend::setFresh( uint32_t domain_id ) { size_t len; @@ -370,7 +434,7 @@ void OdbxBackend::setFresh( u_int32_t domain_id ) -void OdbxBackend::setNotified( u_int32_t domain_id, u_int32_t serial ) +void OdbxBackend::setNotified( uint32_t domain_id, uint32_t serial ) { try { diff --git a/modules/opendbxbackend/odbxbackend.hh b/modules/opendbxbackend/odbxbackend.hh index 2387c91f10..cc44b0d54d 100644 --- a/modules/opendbxbackend/odbxbackend.hh +++ b/modules/opendbxbackend/odbxbackend.hh @@ -45,8 +45,8 @@ using std::vector; -bool checkSlave( u_int32_t last, u_int32_t notified, SOAData* sd, DomainInfo* di ); -bool checkMaster( u_int32_t last, u_int32_t notified, SOAData* sd, DomainInfo* di ); +bool checkSlave( uint32_t last, uint32_t notified, SOAData* sd, DomainInfo* di ); +bool checkMaster( uint32_t last, uint32_t notified, SOAData* sd, DomainInfo* di ); class OdbxBackend : public DNSBackend @@ -65,7 +65,7 @@ class OdbxBackend : public DNSBackend string escape( const string& str, QueryType type ); bool connectTo( const vector& host, QueryType type ); - bool getDomainList( const string& query, vector* list, bool (*check_fcn)(u_int32_t,u_int32_t,SOAData*,DomainInfo*) ); + bool getDomainList( const string& query, vector* list, bool (*check_fcn)(uint32_t,uint32_t,SOAData*,DomainInfo*) ); bool execStmt( const char* stmt, unsigned long length, QueryType type ); bool getRecord( QueryType type ); @@ -76,6 +76,7 @@ public: ~OdbxBackend(); void lookup( const QType& qtype, const string& qdomain, DNSPacket* p = 0, int zoneid = -1 ); + bool getSOA( const string& domain, SOAData& sd, DNSPacket* p ); bool list( const string& target, int domain_id ); bool get( DNSResourceRecord& rr ); @@ -92,8 +93,8 @@ public: void getUpdatedMasters( vector* updated ); void getUnfreshSlaveInfos( vector* unfresh ); - void setFresh( u_int32_t domain_id ); - void setNotified( u_int32_t domain_id, u_int32_t serial ); + void setFresh( uint32_t domain_id ); + void setNotified( uint32_t domain_id, uint32_t serial ); }; @@ -116,15 +117,16 @@ public: declare( suffix, "username","User for connecting to the DBMS","powerdns"); declare( suffix, "password","Password for connecting to the DBMS",""); - declare( suffix, "sql-list", "AXFR query", "SELECT \"domain_id\", \"name\", \"type\", \"ttl\", \"prio\", \"content\" FROM \"records\" WHERE \"domain_id\"=:id" ); + declare( suffix, "sql-list", "AXFR query", "SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"domain_id\"=:id" ); - declare( suffix, "sql-lookup", "Lookup query","SELECT \"domain_id\", \"name\", \"type\", \"ttl\", \"prio\", \"content\" FROM \"records\" WHERE \"name\"=':name'" ); - declare( suffix, "sql-lookupid", "Lookup query with id","SELECT \"domain_id\", \"name\", \"type\", \"ttl\", \"prio\", \"content\" FROM \"records\" WHERE \"domain_id\"=:id AND \"name\"=':name'" ); - declare( suffix, "sql-lookuptype", "Lookup query with type","SELECT \"domain_id\", \"name\", \"type\", \"ttl\", \"prio\", \"content\" FROM \"records\" WHERE \"name\"=':name' AND \"type\"=':type'" ); - declare( suffix, "sql-lookuptypeid", "Lookup query with type and id","SELECT \"domain_id\", \"name\", \"type\", \"ttl\", \"prio\", \"content\" FROM \"records\" WHERE \"domain_id\"=:id AND \"name\"=':name' AND \"type\"=':type'" ); + declare( suffix, "sql-lookup", "Lookup query","SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"name\"=':name'" ); + declare( suffix, "sql-lookupid", "Lookup query with id","SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"domain_id\"=:id AND r.\"name\"=':name'" ); + declare( suffix, "sql-lookuptype", "Lookup query with type","SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"name\"=':name' AND r.\"type\"=':type'" ); + declare( suffix, "sql-lookuptypeid", "Lookup query with type and id","SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"domain_id\"=:id AND r.\"name\"=':name' AND r.\"type\"=':type'" ); + declare( suffix, "sql-lookupsoa","Lookup query for SOA record","SELECT d.\"id\", d.\"auto_serial\", r.\"content\" FROM \"records\" r JOIN \"domains\" d ON r.\"domain_id\"=d.\"id\" WHERE r.\"name\"=':name' AND r.\"type\"='SOA' AND d.\"status\"='A'" ); - declare( suffix, "sql-zonedelete","Delete all records for this zone","DELETE FROM \"records\" WHERE \"domain_id\"=:id" ); - declare( suffix, "sql-zoneinfo","Get domain info","SELECT d.\"id\", d.\"name\", d.\"type\", d.\"master\", d.\"last_check\", r.\"content\" FROM \"domains\" d LEFT JOIN \"records\" r ON ( d.\"id\"=r.\"domain_id\" AND r.\"type\"='SOA' ) WHERE d.\"name\"=':name' AND d.\"status\"='A'" ); + declare( suffix, "sql-zonedelete","Delete all records for this zone","DELETE FROM \"records\" r WHERE r.\"domain_id\"=:id" ); + declare( suffix, "sql-zoneinfo","Get domain info","SELECT d.\"id\", d.\"name\", d.\"type\", d.\"master\", d.\"last_check\", d.\"auto_serial\", r.\"content\" FROM \"domains\" d LEFT JOIN \"records\" r ON ( d.\"id\"=r.\"domain_id\" AND r.\"type\"='SOA' ) WHERE d.\"name\"=':name' AND d.\"status\"='A'" ); declare( suffix, "sql-transactbegin", "Start transaction", "BEGIN" ); declare( suffix, "sql-transactend", "Finish transaction", "COMMIT" ); @@ -133,14 +135,14 @@ public: declare( suffix, "sql-insert-slave","Add slave domain", "INSERT INTO \"domains\" ( \"name\", \"type\", \"master\", \"account\" ) VALUES ( '%s', 'SLAVE', '%s', '%s' )" ); declare( suffix, "sql-insert-record","Feed record into table", "INSERT INTO \"records\" ( \"domain_id\", \"name\", \"type\", \"ttl\", \"prio\", \"content\" ) VALUES ( %d, '%s', '%s', %d, %d, '%s' )" ); - declare( suffix, "sql-update-serial", "Set zone to notified", "UPDATE \"domains\" SET \"notified_serial\"=%d WHERE \"id\"=%d" ); - declare( suffix, "sql-update-lastcheck", "Set time of last check", "UPDATE \"domains\" SET \"last_check\"=%d WHERE \"id\"=%d" ); + declare( suffix, "sql-update-serial", "Set zone to notified", "UPDATE \"domains\" d SET d.\"notified_serial\"=%d WHERE d.\"id\"=%d" ); + declare( suffix, "sql-update-lastcheck", "Set time of last check", "UPDATE \"domains\" d SET d.\"last_check\"=%d WHERE d.\"id\"=%d" ); - declare( suffix, "sql-master", "Get master record for zone", "SELECT \"master\" FROM \"domains\" WHERE \"name\"=':name' AND \"status\"='A' AND \"type\"='SLAVE'" ); - declare( suffix, "sql-supermaster","Get supermaster info", "SELECT \"account\" FROM \"supermasters\" WHERE \"ip\"=':ip' AND \"nameserver\"=':ns'" ); + declare( suffix, "sql-master", "Get master record for zone", "SELECT d.\"master\" FROM \"domains\" d WHERE d.\"name\"=':name' AND d.\"status\"='A' AND d.\"type\"='SLAVE'" ); + declare( suffix, "sql-supermaster","Get supermaster info", "SELECT s.\"account\" FROM \"supermasters\" s WHERE s.\"ip\"=':ip' AND s.\"nameserver\"=':ns'" ); - declare( suffix, "sql-infoslaves", "Get all unfresh slaves", "SELECT d.\"id\", d.\"name\", d.\"master\", d.\"notified_serial\", d.\"last_check\", r.\"change_date\", r.\"content\" FROM \"domains\" d LEFT JOIN \"records\" r ON ( d.\"id\"=r.\"domain_id\" AND r.\"type\"='SOA' ) WHERE d.\"status\"='A' AND d.\"type\"='SLAVE'" ); - declare( suffix, "sql-infomasters", "Get all updated masters", "SELECT d.\"id\", d.\"name\", d.\"master\", d.\"notified_serial\", d.\"last_check\", r.\"change_date\", r.\"content\" FROM \"domains\" d JOIN \"records\" r ON d.\"id\"=r.\"domain_id\" WHERE d.\"status\"='A' AND d.\"type\"='MASTER' AND r.\"type\"='SOA'" ); + declare( suffix, "sql-infoslaves", "Get all unfresh slaves", "SELECT d.\"id\", d.\"name\", d.\"master\", d.\"last_check\", d.\"notified_serial\", d.\"auto_serial\", r.\"content\" FROM \"domains\" d LEFT JOIN \"records\" r ON ( d.\"id\"=r.\"domain_id\" AND r.\"type\"='SOA' ) WHERE d.\"status\"='A' AND d.\"type\"='SLAVE'" ); + declare( suffix, "sql-infomasters", "Get all updated masters", "SELECT d.\"id\", d.\"name\", d.\"master\", d.\"last_check\", d.\"notified_serial\", d.\"auto_serial\", r.\"content\" FROM \"domains\" d LEFT JOIN \"records\" r ON ( d.\"id\"=r.\"domain_id\" AND r.\"type\"='SOA' ) WHERE d.\"status\"='A' AND d.\"type\"='MASTER'" ); declare( suffix, "host", "depricated, use host-read and host-write instead","" ); } diff --git a/modules/opendbxbackend/odbxprivate.cc b/modules/opendbxbackend/odbxprivate.cc index cabacbc55e..bde9eecbda 100644 --- a/modules/opendbxbackend/odbxprivate.cc +++ b/modules/opendbxbackend/odbxprivate.cc @@ -20,6 +20,13 @@ bool OdbxBackend::connectTo( const vector& hosts, QueryType type ) m_handle[type] = NULL; } + if( type == WRITE && getArg( "backend" ) == "sqlite" ) + { + L.log( m_myname + " Using same SQLite connection for reading and writeing to '" + hosts[odbx_host_index[READ]] + "'", Logger::Notice ); + m_handle[WRITE] = m_handle[READ]; + return true; + } + for( i = 0; i < hosts.size(); i++ ) { h = ( idx + i ) % hosts.size(); @@ -156,10 +163,10 @@ string OdbxBackend::escape( const string& str, QueryType type ) -bool OdbxBackend::getDomainList( const string& stmt, vector* list, bool (*check_fcn)(u_int32_t,u_int32_t,SOAData*,DomainInfo*) ) +bool OdbxBackend::getDomainList( const string& stmt, vector* list, bool (*check_fcn)(uint32_t,uint32_t,SOAData*,DomainInfo*) ) { const char* tmp; - u_int32_t nlast, nserial; + uint32_t nlast, nserial; DomainInfo di; SOAData sd; @@ -188,12 +195,12 @@ bool OdbxBackend::getDomainList( const string& stmt, vector* list, b if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL ) { - nlast = strtol( tmp, NULL, 10 ); + nserial = strtol( tmp, NULL, 10 ); } if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) { - nserial = strtol( tmp, NULL, 10 ); + nlast = strtol( tmp, NULL, 10 ); } if( (*check_fcn)( nlast, nserial, &sd, &di ) ) @@ -228,9 +235,9 @@ bool OdbxBackend::getDomainList( const string& stmt, vector* list, b -bool checkSlave( u_int32_t nlast, u_int32_t nserial, SOAData* sd, DomainInfo* di ) +bool checkSlave( uint32_t nlast, uint32_t nserial, SOAData* sd, DomainInfo* di ) { - if( nlast + sd->refresh < (u_int32_t) time( 0 ) ) + if( nlast + sd->refresh < (uint32_t) time( 0 ) ) { di->kind = DomainInfo::Slave; return true; @@ -241,7 +248,7 @@ bool checkSlave( u_int32_t nlast, u_int32_t nserial, SOAData* sd, DomainInfo* di -bool checkMaster( u_int32_t nlast, u_int32_t nserial, SOAData* sd, DomainInfo* di ) +bool checkMaster( uint32_t nlast, uint32_t nserial, SOAData* sd, DomainInfo* di ) { if( nserial != sd->serial ) {