]> granicus.if.org Git - pdns/commitdiff
auth: Don't reconnect to a SQL backend if we are in a transaction
authorRemi Gacogne <remi.gacogne@powerdns.com>
Sat, 15 Apr 2017 21:17:24 +0000 (23:17 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 13 Jun 2017 13:47:08 +0000 (15:47 +0200)
modules/gmysqlbackend/gmysqlbackend.cc
modules/gmysqlbackend/gmysqlbackend.hh
modules/gpgsqlbackend/gpgsqlbackend.cc
modules/gpgsqlbackend/gpgsqlbackend.hh
modules/gpgsqlbackend/spgsql.hh
pdns/backends/gsql/gsqlbackend.cc
pdns/backends/gsql/gsqlbackend.hh

index cb84b21a6667e23ca9cfcca03d03217809a51272..e0b90123624dff84e8deb496427bd1c00bd3e077 100644 (file)
@@ -62,13 +62,6 @@ void gMySQLBackend::reconnect()
                    getArgAsNum("timeout")));
 }
 
-void gMySQLBackend::reconnectIfNeeded()
-{
-  if (!isConnectionUsable()) {
-    reconnect();
-  }
-}
-
 class gMySQLFactory : public BackendFactory
 {
 public:
index be6acfea236655654677c057dfbe143846f4388e..67f6928a3121173db1b31294e9f724663461c26e 100644 (file)
@@ -35,8 +35,7 @@ class gMySQLBackend : public GSQLBackend
 public:
   gMySQLBackend(const string &mode, const string &suffix); //!< Makes our connection to the database. Throws an exception if it fails.
 protected:
-  void reconnectIfNeeded() override;
-  void reconnect();
+  void reconnect() override;
 };
 
 #endif /* PDNS_GMYSQLBACKEND_HH */
index f41ccd0b233284d46b7cec3d64c8e65ff5a17ec1..ab43d80b5ee4893a84ace03c42a4957aed24a3f5 100644 (file)
@@ -54,6 +54,22 @@ gPgSQLBackend::gPgSQLBackend(const string &mode, const string &suffix)  : GSQLBa
   L<<Logger::Info<<mode<<" Connection successful. Connected to database '"<<getArg("dbname")<<"' on '"<<getArg("host")<<"'."<<endl;
 }
 
+void gPgSQLBackend::reconnect()
+{
+  if (d_db) {
+    d_db->reconnect();
+  }
+}
+
+bool gPgSQLBackend::inTransaction()
+{
+  const auto* db = dynamic_cast<SPgSQL*>(d_db);
+  if (db) {
+    return db->in_trx();
+  }
+  return false;
+}
+
 class gPgSQLFactory : public BackendFactory
 {
 public:
index a93f471b6f02db87fdbb7a68b726eeb9806d8b92..b1bef1da95a7192ee09b35db29277ef2d3f1db3a 100644 (file)
@@ -34,6 +34,9 @@ class gPgSQLBackend : public GSQLBackend
 {
 public:
   gPgSQLBackend(const string &mode, const string &suffix); //!< Makes our connection to the database. Throws an exception if it fails.
+protected:
+  void reconnect() override;
+  bool inTransaction() override;
 };
 
 #endif /* PDNS_GPGSQLBACKEND_HH */
index bf39b3ab5fdd77d7156a9947fdebdbe0eac42fa2..6654e4f872a66dd53ed2279e9306c299dd923424 100644 (file)
@@ -47,7 +47,7 @@ public:
   void reconnect() override;
 
   PGconn* db() { return d_db; }
-  bool in_trx() { return d_in_trx; }
+  bool in_trx() const { return d_in_trx; }
 
 private:
   PGconn* d_db;
index 53b2faf6a01c5b1bd4db2aa437953c4380d50eb2..efc9b5def61e765b2ac88516860c9fb6203306a5 100644 (file)
@@ -1464,6 +1464,7 @@ bool GSQLBackend::startTransaction(const DNSName &domain, int domain_id)
     reconnectIfNeeded();
 
     d_db->startTransaction();
+    d_inTransaction = true;
     if(domain_id >= 0) {
       d_DeleteZoneQuery_stmt->
         bind("domain_id", domain_id)->
@@ -1472,6 +1473,7 @@ bool GSQLBackend::startTransaction(const DNSName &domain, int domain_id)
     }
   }
   catch (SSqlException &e) {
+    d_inTransaction = false;
     throw PDNSException("Database failed to start transaction: "+e.txtReason());
   }
 
@@ -1482,8 +1484,10 @@ bool GSQLBackend::commitTransaction()
 {
   try {
     d_db->commit();
+    d_inTransaction = false;
   }
   catch (SSqlException &e) {
+    d_inTransaction = false;
     throw PDNSException("Database failed to commit transaction: "+e.txtReason());
   }
   return true;
@@ -1493,8 +1497,10 @@ bool GSQLBackend::abortTransaction()
 {
   try {
     d_db->rollback();
+    d_inTransaction = false;
   }
   catch(SSqlException &e) {
+    d_inTransaction = false;
     throw PDNSException("Database failed to abort transaction: "+string(e.txtReason()));
   }
   return true;
index 8fdb2393cfde7fa509f5d6501e6efd63eda9a69b..4f8543088d56a162896d85ee1219a89b66bf6c4d 100644 (file)
@@ -250,21 +250,23 @@ protected:
     }
     return false;
   }
-  virtual void reconnectIfNeeded()
+  void reconnectIfNeeded()
   {
-    if (isConnectionUsable()) {
+    if (isConnectionUsable() || inTransaction()) {
       return;
     }
 
-    if (d_db) {
-      d_db->reconnect();
-    }
+    reconnect();
+  }
+  virtual void reconnect() { }
+  virtual bool inTransaction()
+  {
+    return d_inTransaction;
   }
 
 private:
   string d_query_name;
   DNSName d_qname;
-  SSql *d_db;
   SSqlStatement::result_t d_result;
 
   string d_NoIdQuery;
@@ -402,7 +404,9 @@ private:
   SSqlStatement* d_SearchCommentsQuery_stmt;
 
 protected:
+  SSql *d_db{nullptr};
   bool d_dnssecQueries;
+  bool d_inTransaction{false};
 };
 
 #endif /* PDNS_GSQLBACKEND_HH */