Skip to content

Commit

Permalink
Move ADatabase in APool
Browse files Browse the repository at this point in the history
  • Loading branch information
dantti committed Jun 11, 2023
1 parent 2e43e76 commit 48795ae
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 28 deletions.
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ Standard: Cpp11
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
WhitespaceSensitiveMacros:
- C_ATTR
UseTab: Never

...
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: MIT

cmake_minimum_required(VERSION 3.16)
project(libasql VERSION 0.79.0 LANGUAGES CXX)
project(libasql VERSION 0.80.0 LANGUAGES CXX)

include(GNUInstallDirs)

Expand Down
50 changes: 50 additions & 0 deletions demos/async1/async1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,47 @@

using namespace ASql;

void recursiveLoop()
{
auto db = APool::database(u"memory_loop");
db.exec(u"SELECT now()", {QJsonObject{{QStringLiteral("foo"), true}}}, nullptr, [](AResult &result) {
if (result.error()) {
qDebug() << "Error memory_loop" << result.errorString();
} else {
recursiveLoop();
}
});
}

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

{
APool::create(APg::factory(QStringLiteral("postgres:///")), u"move_db_pool");
APool::setMaxConnections(1, u"move_db_pool");
APool::database(
nullptr, [](ADatabase db) {
db.exec(u"SELECT 'I ♥ Cutelyst!' AS utf8", nullptr, [](AResult &result) {
qDebug() << "=====iterator single row" << result.toHash();
if (result.error()) {
qDebug() << "Error" << result.errorString();
}
});
},
u"move_db_pool");
APool::database(
nullptr, [](ADatabase db) {
db.exec(u"SELECT 'I ♥ Cutelyst!' AS utf8", nullptr, [](AResult &result) {
qDebug() << "=====iterator single row" << result.toHash();
if (result.error()) {
qDebug() << "Error" << result.errorString();
}
});
},
u"move_db_pool");
}

{
// regresion test crash - where selfDriver gets released
APool::create(APg::factory(QStringLiteral("postgres:///")), u"delete_db_after_use");
Expand All @@ -42,6 +79,19 @@ int main(int argc, char *argv[])
}
}

{
// memory loop
APool::create(APg::factory(QStringLiteral("postgres:///")), u"memory_loop");
APool::setMaxIdleConnections(5, u"memory_loop");
// APool::setMaxConnections(0, u"memory_loop");

{
for (int i = 0; i < 20; ++i) {
recursiveLoop();
}
}
}

APool::create(APg::factory(QStringLiteral("postgres:///")));
APool::setMaxIdleConnections(10);

Expand Down
4 changes: 2 additions & 2 deletions demos/async1/deleter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ int main(int argc, char *argv[])
QCoreApplication app(argc, argv);

APool::create(APg::factory(QStringLiteral("postgres:///?target_session_attrs=read-write")));
APool::setSetupCallback([](ADatabase &db) {
APool::setSetupCallback([](ADatabase db) {
qDebug() << "setup db";
db.exec(u"SET TIME ZONE 'Europe/Rome';", nullptr, [](AResult &result) {
qDebug() << "SETUP" << result.error() << result.errorString() << result.toJsonObject();
});
});

APool::setReuseCallback([](ADatabase &db) {
APool::setReuseCallback([](ADatabase db) {
qDebug() << "reuse db";
db.exec(u"DISCARD ALL", nullptr, [](AResult &result) {
qDebug() << "REUSE" << result.error() << result.errorString() << result.toJsonObject();
Expand Down
2 changes: 1 addition & 1 deletion demos/async1/prepared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ int main(int argc, char *argv[])

// ADatabase().rollback(); assert

APool::database(nullptr, [=](ADatabase &db) {
APool::database(nullptr, [=](ADatabase db) {
qDebug() << "Got db" << db.isOpen() << db.state();

db.exec(QStringLiteral("SELECT now()"), nullptr, [=](AResult &result) {
Expand Down
5 changes: 5 additions & 0 deletions src/adatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ ADatabase::ADatabase(const std::shared_ptr<ADriver> &driver)
{
}

ADatabase::ADatabase(std::shared_ptr<ADriver> &&driver)
: d(driver)
{
}

ADatabase::ADatabase(const std::shared_ptr<ADriverFactory> &factory)
: d(factory->createDriver())
{
Expand Down
5 changes: 5 additions & 0 deletions src/adatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ class ASQL_EXPORT ADatabase
*/
ADatabase(const std::shared_ptr<ADriver> &driver);

/*!
* \brief ADatabase contructs an database object with the supplied driver
*/
ADatabase(std::shared_ptr<ADriver> &&driver);

/*!
* \brief ADatabase contructs an database object with the supplied driver factory
*/
Expand Down
51 changes: 30 additions & 21 deletions src/apool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Q_LOGGING_CATEGORY(ASQL_POOL, "asql.pool", QtInfoMsg)
using namespace ASql;

struct APoolQueuedClient {
std::function<void(ADatabase &)> cb;
ADatabaseFn cb;
QPointer<QObject> receiver;
bool checkReceiver;
};
Expand All @@ -28,8 +28,8 @@ struct APoolInternal {
std::shared_ptr<ADriverFactory> driverFactory;
QVector<ADriver *> pool;
std::queue<APoolQueuedClient> connectionQueue;
std::function<void(ADatabase &)> setupCb;
std::function<void(ADatabase &)> reuseCb;
ADatabaseFn setupCb;
ADatabaseFn reuseCb;
int maxIdleConnections = 1;
int maximuConnections = 0;
int connectionCount = 0;
Expand Down Expand Up @@ -85,11 +85,10 @@ void APool::pushDatabaseBack(QStringView connectionName, ADriver *driver)
continue;
}

ADatabase db;
db.d = std::shared_ptr<ADriver>(driver, [connectionName](ADriver *driver) {
ADatabase db{std::shared_ptr<ADriver>(driver, [connectionName](ADriver *driver) {
pushDatabaseBack(connectionName, driver);
});
client.cb(db);
})};
client.cb(std::move(db));
return;
}

Expand All @@ -114,7 +113,7 @@ ADatabase APool::database(QStringView poolName)
APoolInternal &iPool = it.value();
if (iPool.pool.empty()) {
if (iPool.maximuConnections && iPool.connectionCount >= iPool.maximuConnections) {
qWarning(ASQL_POOL) << "Maximum number of connections reached" << poolName << iPool.connectionCount << iPool.maximuConnections;
qCritical(ASQL_POOL) << "Maximum number of connections reached" << poolName << iPool.connectionCount << iPool.connectionQueue.size();
} else {
++iPool.connectionCount;
auto driver = iPool.driverFactory->createRawDriver();
Expand Down Expand Up @@ -154,15 +153,14 @@ int APool::currentConnections(QStringView poolName)
return 0;
}

void APool::database(QObject *receiver, std::function<void(ADatabase &)> cb, QStringView poolName)
void APool::database(QObject *receiver, ADatabaseFn cb, QStringView poolName)
{
ADatabase db;
auto it = m_connectionPool.find(poolName);
if (it != m_connectionPool.end()) {
APoolInternal &iPool = it.value();
if (iPool.pool.empty()) {
if (iPool.maximuConnections && iPool.connectionCount >= iPool.maximuConnections) {
qInfo(ASQL_POOL) << "Maximum number of connections reached, queuing" << poolName << iPool.connectionCount << iPool.maximuConnections;
qInfo(ASQL_POOL) << "Maximum number of connections reached, queuing" << poolName << iPool.connectionCount << iPool.connectionQueue.size();
APoolQueuedClient queued;
queued.cb = cb;
queued.receiver = receiver;
Expand All @@ -172,31 +170,42 @@ void APool::database(QObject *receiver, std::function<void(ADatabase &)> cb, QSt
}
++iPool.connectionCount;
qDebug(ASQL_POOL) << "Creating a database connection for pool" << poolName;
db.d = std::shared_ptr<ADriver>(iPool.driverFactory->createRawDriver(), [poolName](ADriver *driver) {
ADatabase db{std::shared_ptr<ADriver>(iPool.driverFactory->createRawDriver(), [poolName](ADriver *driver) {
pushDatabaseBack(poolName, driver);
});
})};

if (iPool.setupCb) {
iPool.setupCb(db);
}

db.open();
if (cb) {
cb(std::move(db));
}
} else {
qDebug(ASQL_POOL) << "Reusing a database connection from pool" << poolName;
ADriver *priv = iPool.pool.takeLast();
db.d = std::shared_ptr<ADriver>(priv, [poolName](ADriver *driver) {
ADatabase db{std::shared_ptr<ADriver>(priv, [poolName](ADriver *driver) {
pushDatabaseBack(poolName, driver);
});
})};

if (iPool.reuseCb) {
iPool.reuseCb(db);
}

db.open();
if (cb) {
cb(std::move(db));
}
}
} else {
qCritical(ASQL_POOL) << "Database pool NOT FOUND" << poolName;
}
db.open();

if (cb) {
cb(db);
ADatabase db;
db.open();
if (cb) {
cb(std::move(db));
}
}
}

Expand All @@ -220,7 +229,7 @@ void APool::setMaxConnections(int max, QStringView poolName)
}
}

void APool::setSetupCallback(std::function<void(ADatabase &)> cb, QStringView poolName)
void APool::setSetupCallback(ADatabaseFn cb, QStringView poolName)
{
auto it = m_connectionPool.find(poolName);
if (it != m_connectionPool.end()) {
Expand All @@ -230,7 +239,7 @@ void APool::setSetupCallback(std::function<void(ADatabase &)> cb, QStringView po
}
}

void APool::setReuseCallback(std::function<void(ADatabase &)> cb, QStringView poolName)
void APool::setReuseCallback(ADatabaseFn cb, QStringView poolName)
{
auto it = m_connectionPool.find(poolName);
if (it != m_connectionPool.end()) {
Expand Down
8 changes: 5 additions & 3 deletions src/apool.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

namespace ASql {

using ADatabaseFn = std::function<void(ADatabase db)>;

class ASQL_EXPORT APool
{
public:
Expand Down Expand Up @@ -80,7 +82,7 @@ class ASQL_EXPORT APool
* \param receiver
* \param connectionName
*/
static void database(QObject *receiver, std::function<void(ADatabase &database)> cb, QStringView poolName = defaultPool);
static void database(QObject *receiver, ADatabaseFn cb, QStringView poolName = defaultPool);

/*!
* \brief setMaxIdleConnections maximum number of idle connections of the pool
Expand Down Expand Up @@ -123,7 +125,7 @@ class ASQL_EXPORT APool
* \param max
* \param poolName
*/
static void setSetupCallback(std::function<void(ADatabase &database)> cb, QStringView poolName = defaultPool);
static void setSetupCallback(ADatabaseFn cb, QStringView poolName = defaultPool);

/*!
* \brief setReuseCallback setup a connection before being reused
Expand All @@ -141,7 +143,7 @@ class ASQL_EXPORT APool
* \param max
* \param poolName
*/
static void setReuseCallback(std::function<void(ADatabase &database)> cb, QStringView poolName = defaultPool);
static void setReuseCallback(ADatabaseFn cb, QStringView poolName = defaultPool);

private:
inline static void pushDatabaseBack(QStringView connectionName, ADriver *driver);
Expand Down

0 comments on commit 48795ae

Please sign in to comment.