Commit 89a62c44 authored by Ronan's avatar Ronan

feat(MainDb): forward transaction in with lambda

parent c0e48a83
......@@ -294,7 +294,6 @@ if (SOCI_FOUND)
list(APPEND LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
db/internal/db-exception-handler.h
db/internal/smart-transaction.h
db/internal/statements.h
)
......
......@@ -22,18 +22,40 @@
#include <soci/soci.h>
#include "db/main-db.h"
#include "db/main-db-p.h"
#include "logger/logger.h"
// =============================================================================
#define L_DB_EXCEPTION_HANDLER_C(CONTEXT) \
LinphonePrivate::DbExceptionHandlerInfo().set(__func__, CONTEXT) * [&]()
LinphonePrivate::DbExceptionHandlerInfo().set(__func__, CONTEXT) * [&](SmartTransaction &tr)
#define L_DB_EXCEPTION_HANDLER L_DB_EXCEPTION_HANDLER_C(this)
LINPHONE_BEGIN_NAMESPACE
class SmartTransaction {
public:
SmartTransaction (soci::session *session, const char *name) : mTransaction(*session), mName(name) {
lInfo() << "Start transaction " << this << " in `" << mName << "`.";
}
~SmartTransaction () {
lInfo() << "Rollback transaction " << this << " in `" << mName << "`.";
}
void commit () {
lInfo() << "Commit transaction " << this << " in `" << mName << "`.";
mTransaction.commit();
}
private:
soci::transaction mTransaction;
const char *mName;
L_DISABLE_COPY(SmartTransaction);
};
struct DbExceptionHandlerInfo {
DbExceptionHandlerInfo &set (const char *_name, const MainDb *_mainDb) {
name = _name;
......@@ -47,7 +69,9 @@ struct DbExceptionHandlerInfo {
template<typename Function>
class DbExceptionHandler {
using InternalReturnType = typename std::remove_reference<decltype(std::declval<Function>()())>::type;
using InternalReturnType = typename std::remove_reference<
decltype(std::declval<Function>()(std::declval<SmartTransaction &>()))
>::type;
public:
using ReturnType = typename std::conditional<
......@@ -57,26 +81,29 @@ public:
>::type;
DbExceptionHandler (DbExceptionHandlerInfo &info, Function function) : mFunction(std::move(function)) {
const char *name = info.name;
try {
mResult= exec<InternalReturnType>();
SmartTransaction tr(info.mainDb->getPrivate()->dbSession.getBackendSession(), name);
mResult = exec<InternalReturnType>(tr);
} catch (const soci::soci_error &e) {
lWarning() << "Catched exception in MainDb::" << info.name << "(" << e.what() << ").";
lWarning() << "Catched exception in MainDb::" << name << "(" << e.what() << ").";
soci::soci_error::error_category category = e.get_error_category();
if (
(category == soci::soci_error::connection_error || category == soci::soci_error::unknown) &&
info.mainDb->forceReconnect()
) {
try {
mResult = exec<InternalReturnType>();
SmartTransaction tr(info.mainDb->getPrivate()->dbSession.getBackendSession(), name);
mResult = exec<InternalReturnType>(tr);
} catch (const std::exception &e) {
lError() << "Unable to execute query after reconnect in MainDb::" << info.name << "(" << e.what() << ").";
lError() << "Unable to execute query after reconnect in MainDb::" << name << "(" << e.what() << ").";
}
return;
}
lError() << "Unhandled [" << getErrorCategoryAsString(category) << "] exception in MainDb::" <<
info.name << ": `" << e.what() << "`.";
name << ": `" << e.what() << "`.";
} catch (const std::exception &e) {
lError() << "Unhandled generic exception in MainDb::" << info.name << ": `" << e.what() << "`.";
lError() << "Unhandled generic exception in MainDb::" << name << ": `" << e.what() << "`.";
}
}
......@@ -89,15 +116,15 @@ public:
private:
// Exec function with no return type.
template<typename T>
typename std::enable_if<std::is_same<T, void>::value, bool>::type exec () const {
mFunction();
typename std::enable_if<std::is_same<T, void>::value, bool>::type exec (SmartTransaction &tr) const {
mFunction(tr);
return true;
}
// Exec function with return type.
template<typename T>
typename std::enable_if<!std::is_same<T, void>::value, T>::type exec () const {
return mFunction();
typename std::enable_if<!std::is_same<T, void>::value, T>::type exec (SmartTransaction &tr) const {
return mFunction(tr);
}
static const char *getErrorCategoryAsString (soci::soci_error::error_category category) {
......
/*
* smart-transaction.h
* Copyright (C) 2010-2018 Belledonne Communications SARL
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _L_SMART_TRANSACTION_H_
#define _L_SMART_TRANSACTION_H_
#include <soci/soci.h>
#include "logger/logger.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
class SmartTransaction {
public:
SmartTransaction (soci::session *session, const char *name) : mTransaction(*session), mName(name) {
lInfo() << "Start transaction " << this << " in `" << mName << "`.";
}
~SmartTransaction () {
lInfo() << "Rollback transaction " << this << " in `" << mName << "`.";
}
void commit () {
lInfo() << "Commit transaction " << this << " in `" << mName << "`.";
mTransaction.commit();
}
private:
soci::transaction mTransaction;
const char *mName;
L_DISABLE_COPY(SmartTransaction);
};
LINPHONE_END_NAMESPACE
#endif // ifndef _L_SMART_TRANSACTION_H_
......@@ -39,7 +39,6 @@
#ifdef SOCI_ENABLED
#include "internal/db-exception-handler.h"
#include "internal/smart-transaction.h"
#include "internal/statements.h"
#endif // ifdef SOCI_ENABLED
......@@ -1785,8 +1784,6 @@ bool MainDb::addEvent (const shared_ptr<EventLog> &eventLog) {
long long storageId = 0;
SmartTransaction tr(d->dbSession.getBackendSession(), __func__);
EventLog::Type type = eventLog->getType();
switch (type) {
case EventLog::Type::None:
......@@ -1847,8 +1844,6 @@ bool MainDb::updateEvent (const shared_ptr<EventLog> &eventLog) {
return L_DB_EXCEPTION_HANDLER {
L_D();
SmartTransaction tr(d->dbSession.getBackendSession(), __func__);
switch (eventLog->getType()) {
case EventLog::Type::None:
return false;
......@@ -1950,7 +1945,6 @@ shared_ptr<EventLog> MainDb::getEventFromKey (const MainDbKey &dbKey) {
return L_DB_EXCEPTION_HANDLER_C(q.get()) {
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
string peerSipAddress;
string localSipAddress;
......@@ -1989,7 +1983,6 @@ list<shared_ptr<EventLog>> MainDb::getConferenceNotifiedEvents (
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId);
......@@ -2032,7 +2025,6 @@ int MainDb::getChatMessageCount (const ChatRoomId &chatRoomId) const {
" SELECT event_id FROM conference_event WHERE chat_room_id = :chatRoomId"
")";
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId);
*session << query, soci::use(dbChatRoomId), soci::into(count);
}
......@@ -2066,7 +2058,6 @@ int MainDb::getUnreadChatMessageCount (const ChatRoomId &chatRoomId) const {
if (!chatRoomId.isValid())
*session << query, soci::into(count);
else {
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId);
*session << query, soci::use(dbChatRoomId), soci::into(count);
}
......@@ -2101,7 +2092,6 @@ void MainDb::markChatMessagesAsRead (const ChatRoomId &chatRoomId) const {
if (!chatRoomId.isValid())
*session << query;
else {
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId);
*session << query, soci::use(dbChatRoomId);
tr.commit();
......@@ -2130,7 +2120,6 @@ list<shared_ptr<ChatMessage>> MainDb::getUnreadChatMessages (const ChatRoomId &c
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
long long dbChatRoomId;
if (chatRoomId.isValid())
......@@ -2258,7 +2247,6 @@ list<shared_ptr<ChatMessage>> MainDb::findChatMessages (
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
list<shared_ptr<ChatMessage>> chatMessages;
......@@ -2331,7 +2319,6 @@ list<shared_ptr<EventLog>> MainDb::getHistoryRange (
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
shared_ptr<Core> core = getCore();
shared_ptr<AbstractChatRoom> chatRoom = core->findChatRoom(chatRoomId);
......@@ -2396,7 +2383,6 @@ int MainDb::getHistorySize (const ChatRoomId &chatRoomId, FilterMask mask) const
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
int count;
const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId);
......@@ -2411,7 +2397,6 @@ void MainDb::loadChatMessageContents (const shared_ptr<ChatMessage> &chatMessage
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
bool hasFileTransferContent = false;
......@@ -2487,7 +2472,6 @@ void MainDb::cleanHistory (const ChatRoomId &chatRoomId, FilterMask mask) {
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId);
......@@ -2516,7 +2500,6 @@ list<shared_ptr<AbstractChatRoom>> MainDb::getChatRooms () const {
shared_ptr<Core> core = getCore();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
soci::rowset<soci::row> rows = (session->prepare << query);
for (const auto &row : rows) {
......@@ -2645,7 +2628,6 @@ void MainDb::insertChatRoom (const shared_ptr<AbstractChatRoom> &chatRoom) {
L_DB_EXCEPTION_HANDLER {
L_D();
SmartTransaction tr(d->dbSession.getBackendSession(), __func__);
d->insertChatRoom(chatRoom);
tr.commit();
};
......@@ -2660,7 +2642,6 @@ void MainDb::deleteChatRoom (const ChatRoomId &chatRoomId) {
L_DB_EXCEPTION_HANDLER {
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId);
......@@ -2688,7 +2669,6 @@ void MainDb::migrateBasicToClientGroupChatRoom (
// TODO: Update events and chat messages. (Or wait signals.)
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(basicChatRoom->getChatRoomId());
......@@ -2739,7 +2719,6 @@ IdentityAddress MainDb::findMissingOneToOneConferenceChatRoomParticipantAddress
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
string missingParticipantAddress;
string participantASipAddress;
......@@ -2773,7 +2752,6 @@ IdentityAddress MainDb::findOneToOneConferenceChatRoomAddress (
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
const long long &participantASipAddressId = d->selectSipAddressId(participantA.asString());
const long long &participantBSipAddressId = d->selectSipAddressId(participantB.asString());
......@@ -2799,8 +2777,6 @@ void MainDb::insertOneToOneConferenceChatRoom (const shared_ptr<AbstractChatRoom
L_DB_EXCEPTION_HANDLER {
L_D();
SmartTransaction tr(d->dbSession.getBackendSession(), __func__);
const list<shared_ptr<Participant>> &participants = chatRoom->getParticipants();
const long long &participantASipAddressId = d->selectSipAddressId(participants.front()->getAddress().asString());
const long long &participantBSipAddressId = d->selectSipAddressId(participants.back()->getAddress().asString());
......@@ -2826,7 +2802,6 @@ void MainDb::enableChatRoomMigration (const ChatRoomId &chatRoomId, bool enable)
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId);
......@@ -2852,7 +2827,6 @@ void MainDb::updateChatRoomParticipantDevice (
L_D();
soci::session *session = d->dbSession.getBackendSession();
SmartTransaction tr(session, __func__);
const long long &dbChatRoomId = d->selectChatRoomId(chatRoom->getChatRoomId());
const long long &participantSipAddressId = d->selectSipAddressId(device->getParticipant()->getAddress().asString());
......
......@@ -42,6 +42,9 @@ class MainDbPrivate;
class ParticipantDevice;
class MainDb : public AbstractDb, public CoreAccessor {
template<typename Function>
friend class DbExceptionHandler;
friend class MainDbChatMessageKey;
friend class MainDbEventKey;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment