Libpqxx Connection Pool

I am trying to create a very simple and simple connection pool using the libpqxx library. I am completely new to C ++ and still very confused by pointers and links. The behavior of the class is very simple: to have a vector with some initialized connection and pop, and click the connections on the vector when they are needed. The code has many errors due to poor implementation of pointers and references. Could you give me some advice?

EDIT: I managed to fix all the compilation errors. This gives me a segmentation error when I run the main function.

class DbPool { 

public:

 pqxx::result runQuery(const string& query) { connection *conn = getCon(); work trans(*conn); result res = trans.exec(query); trans.commit(); releaseCon(conn); return res; } DbPool(uint32_t max_cons) { for (uint32_t i = 0; i < max_cons; i++) { connection* con = createCon(); m_freeCons.push_back(shared_ptr < connection > (con)); } } 

private:

 connection * createCon() { connection * conn = new connection( "user='ak' password='rootpassword' dbname='bips_office' hostaddr='127.0.0.1' port='5432'"); return conn; } void releaseCon(connection *con) { m_freeCons.push_back(shared_ptr < connection > (con)); } connection* getCon() { shared_ptr < connection > conn = *(m_freeCons.end() - 1); m_freeCons.pop_back(); return conn.get(); } vector<shared_ptr<connection> > m_freeCons; 

};

 int main(int argc, char *argv[]) { DbPool *pool = new DbPool(5); result res = pool->runQuery("SELECT COUNT (*) from captures"); return 0; } 
+4
source share
2 answers

If design issues are your concern, here are my five cents:

  • Is your code compiled? I think not, because you have a vector of connection pointers, but you push away connection objects ( m_freeCons.push_back(*con); - the * separates the connection pointer) ...
  • It's usually a bad idea to give out modifiable descriptors to members (as you do in the getCon method), at least return connection const * if possible
  • If you need to use a set of pointers, consider using shared_ptr instead of raw pointers - this way you don't have to worry about freeing up memory; or use Boost.PointerContainer ; also see here .
  • Just a weird-style question: why are you using return &(*conn) ? This delimits the conn pointer, and then returns the address again. Instead, you can simply write return conn !

In response to your rewritten question with shared_ptr s: you still need to create a connection to the new one and wrap it with shared_ptr; for example for createCon:

 connection * createCon(){ connection * conn = new connection("user='ak' password='rootpassword' dbname='bips_office' hostaddr='127.0.0.1' port='5432'"); return conn; } 

and

  connection* con = createCon(); m_freeCons.push_back(shared_ptr<connection>(con)); 

and similarly in other places.

+2
source

Inspired by your post, I used this simple connection pool in my own project. I used std :: stack. push and pop. When adding connections, error checking is not performed, except for attempts. For postgresql-db.

Database.hpp:

 #include <stack> #include <pqxx/pqxx> class Database { private: const std::string connectionString = "dbname=db user=usr hostaddr=127.0.0.1 port=5432"; std::stack<pqxx::connection *> dbpool; public: Database(const unsigned int); 

Database.cpp:

 #include "Database.hpp" Database::Database(const unsigned int connections) { for (int i = 0; i < connections; ++i) { try { auto* dbconn = new pqxx::connection(connectionString); dbpool.emplace(dbconn); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } } 

main.cpp:

 #include "Database.hpp" int main(int argc, char* argv[]) { Database database {10}; auto *D = dbpool.top(); dbpool.pop(); const std::string query = "select * from mytable"; pqxx::nontransaction N(*D); pqxx::result R(N.exec(query)); for (pqxx::result::const_iterator c = R.begin(); c != R.end(); ++c) { std::cout << c[1].as<std::string>() << std::endl; }; dbpool.push(D); } 
+1
source

Source: https://habr.com/ru/post/1435470/


All Articles