From 379bb2525c93460d692e24cf57244e3e61c569e2 Mon Sep 17 00:00:00 2001
From: Armin Felder <armin.felder@osalliance.com>
Date: Mon, 17 Dec 2018 22:56:03 +0100
Subject: [PATCH] ad

---
 persistancelayer.cpp                  | 642 ++++++++++++++------------
 persistancelayer.h                    |  43 +-
 rocketchat.cpp                        |  18 +-
 rocketchatserver.cpp                  | 121 +++--
 rocketchatserver.h                    |  14 +-
 segfaulthandler.cpp                   |   2 +-
 services/messageservice.cpp           |   2 +-
 services/rocketchatchannelservice.cpp |   4 +-
 8 files changed, 478 insertions(+), 368 deletions(-)

diff --git a/persistancelayer.cpp b/persistancelayer.cpp
index b1b5ec2..9940e83 100755
--- a/persistancelayer.cpp
+++ b/persistancelayer.cpp
@@ -50,6 +50,8 @@ PersistanceLayer *PersistanceLayer::instance()
 
 void PersistanceLayer::initShema()
 {
+    initQueries();
+    mDb.transaction();
     QSqlQuery pragmaquery;
     pragmaquery.prepare( QStringLiteral( "PRAGMA synchronous = OFF" ) );
 
@@ -57,10 +59,6 @@ void PersistanceLayer::initShema()
         qDebug() << pragmaquery.lastError();
     }
 
-    //    pragmaquery.prepare("PRAGMA locking_mode = EXCLUSIVE");
-    //    if(!pragmaquery.exec()){
-    //        qDebug() << pragmaquery.lastError();
-    //    }
     pragmaquery.prepare( QStringLiteral( "PRAGMA JOURNAL_MODE=MEMORY" ) );
 
     if ( !pragmaquery.exec() ) {
@@ -73,8 +71,18 @@ void PersistanceLayer::initShema()
         qDebug() << pragmaquery.lastError();
     }
 
-    transaction();
+    pragmaquery.prepare( QStringLiteral( "PRAGMA PAGE_SIZE=4096" ) );
+
+    if ( !pragmaquery.exec() ) {
+        qDebug() << pragmaquery.lastError();
+    }
+
+    /*    pragmaquery.prepare( "PRAGMA locking_mode = EXCLUSIVE" );
 
+        if ( !pragmaquery.exec() ) {
+            qDebug() << pragmaquery.lastError();
+        }
+    */
     QSqlQuery query;
     query.prepare( QStringLiteral( "CREATE TABLE IF NOT EXISTS user_data "
                                    "(id integer primary key,"
@@ -170,7 +178,7 @@ void PersistanceLayer::initShema()
      }
      */
 
-    commit();
+    mDb.commit();
 
     query.prepare( QStringLiteral( "SELECT db_ver FROM app_info WHERE id=0" ) );
     int dbVer = -1;
@@ -187,10 +195,12 @@ void PersistanceLayer::initShema()
         }
     }
 
+    query.finish();
+
     if ( !dbVer ) {
         upgradeSchema();
     } else if ( dbVer == -1 ) {
-        transaction();
+        mDb.transaction();
         query.prepare( QStringLiteral( "CREATE TABLE IF NOT EXISTS app_info"
                                        "(id varchar(30) primary key,"
                                        "db_ver integer,"
@@ -200,15 +210,18 @@ void PersistanceLayer::initShema()
             qWarning() << query.lastError();
         }
 
-        commit();
         QString dbVersion = QString::number( DBVERSION );
         query.prepare( QStringLiteral( "INSERT INTO app_info (db_ver) VALUES(" ) + dbVersion + ")" );
 
         if ( !query.exec() ) {
             qWarning() << query.lastError();
         }
+
+        mDb.commit();
     }
 
+    mDb.transaction();
+
     query.prepare( QStringLiteral( "CREATE TABLE IF NOT EXISTS app_settings"
                                    "(id integer primary key,"
                                    "serverid integer,"
@@ -219,7 +232,7 @@ void PersistanceLayer::initShema()
         qWarning() << query.lastError();
     }
 
-
+    mDb.commit();
 
     query.prepare( QStringLiteral( "SELECT id FROM custom_emojis" ) );
 
@@ -234,6 +247,8 @@ void PersistanceLayer::initShema()
             break;
         }
 
+        query.finish();
+
         if ( size <= 0 ) {
             QFile dump( QStringLiteral( ":/sql/emojis.sql" ) );
 
@@ -241,7 +256,7 @@ void PersistanceLayer::initShema()
                 qWarning() << "error loading dump";
                 qWarning() << dump.errorString();
             } else {
-                transaction();
+                mDb.transaction();
                 QTextStream in( &dump );
                 QString dumpString;
                 dumpString.reserve( 200 );
@@ -259,11 +274,12 @@ void PersistanceLayer::initShema()
                 }
 
                 dump.close();
-                commit();
+                mDb.commit();
             }
         }
     }
 
+    mDb.commit();
 }
 
 void PersistanceLayer::upgradeSchema()
@@ -283,6 +299,8 @@ void PersistanceLayer::upgradeSchema()
             dbVersion = query.value( dbVerIndex ).toInt();
         }
 
+        query.finish();
+
         if ( dbVersion < DBVERSION ) {
             QFile sqlFile;
             int currentTarget = 0;
@@ -310,11 +328,13 @@ void PersistanceLayer::upgradeSchema()
                 sqlFile.setFileName( QStringLiteral( ":/sql/migrations/5.sql" ) );
             }
 
+
+
             if ( !sqlFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
                 qWarning() << "error loading dump";
                 qWarning() << sqlFile.errorString();
             } else {
-                transaction();
+                mDb.transaction();
 
                 QTextStream in( &sqlFile );
                 QString line;
@@ -331,7 +351,7 @@ void PersistanceLayer::upgradeSchema()
                     }
                 }
 
-                commit();
+                mDb.commit();
             }
 
             upgradeSchema();
@@ -343,6 +363,7 @@ void PersistanceLayer::wipeDb()
 
 {
     mDb.close();
+    mDbReady = false;
     QString directory = QStandardPaths::writableLocation( QStandardPaths::AppLocalDataLocation );
     QString filePath = directory + QStringLiteral( "/data.sqlite" );
     QFile file( filePath );
@@ -351,6 +372,13 @@ void PersistanceLayer::wipeDb()
         qWarning() << file.errorString();
     } else {
         qDebug() << "db wiped";
+        QDir fileDownloadsDir( QStandardPaths::writableLocation( QStandardPaths::TempLocation ) + QStringLiteral( "/rocketChat" ) );
+
+        if ( fileDownloadsDir.removeRecursively() ) {
+            qDebug() << "Downloads wiped";
+        } else {
+            qWarning() << "can't wipe downloads";
+        }
     }
 
     init();
@@ -358,36 +386,45 @@ void PersistanceLayer::wipeDb()
 
 void PersistanceLayer::transaction( )
 {
-    // mMutex.lock();
+    commitMutex.lock();
 
-    if ( mCommitCounter == 0 ) {
+    if ( mTransactionCounter == 0 ) {
         if ( !mDb.transaction() ) {
             qWarning() << mDb.lastError();
         }
     }
 
-    mCommitCounter++;
-    // mMutex.unlock();
+    mTransactionCounter++;
+    commitMutex.unlock();
+}
+
+void PersistanceLayer::askForcommit()
+{
+    commitMutex.lock();
+
+    //  mCommitCounter++;
+
+    commitMutex.unlock();
+    commit( );
 }
 
 void PersistanceLayer::commit( )
 {
-    // mMutex.lock();
+    commitMutex.lock();
 
-    /* if ( mCommitCounter ) {
-         mCommitCounter--;
-     }
-    */
-    if ( mCommitCounter ) {
-        if ( !mDb.commit() ) {
-            qWarning() << mDb.lastError();
-        }
+    //if ( mCommitCounter && mCommitCounter == mTransactionCounter ) {
+    qDebug() << "commit !";
 
+    if ( !mDb.commit() ) {
+        qWarning() << mDb.lastError();
+    } else {
         mCommitCounter = 0;
-
+        mTransactionCounter = 0;
     }
 
-    // mMutex.unlock();
+    //}
+
+    commitMutex.unlock();
 }
 
 
@@ -396,69 +433,57 @@ void PersistanceLayer::setUserName( const QString &pUsername )
 
 {
     transaction();
-    QSqlQuery setName;
-    setName.prepare( QStringLiteral( "UPDATE user_data "
-                                     "SET username=:username WHERE id=:id" ) );
-    setName.bindValue( QStringLiteral( ":id" ), 0 );
-    setName.bindValue( QStringLiteral( ":username" ), pUsername );
-
-    if ( !setName.exec() ) {
-        qWarning() << setName.lastError();
+
+    querySetUsername.bindValue( QStringLiteral( ":id" ), 0 );
+    querySetUsername.bindValue( QStringLiteral( ":username" ), pUsername );
+
+    if ( !querySetUsername.exec() ) {
+        qWarning() << querySetUsername.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::setPassword( const QString &pPassword )
 {
     transaction();
-    QSqlQuery setPass;
-    setPass.prepare( QStringLiteral( "UPDATE user_data "
-                                     "SET password=:password WHERE id=:id" ) );
-    setPass.bindValue( QStringLiteral( ":password" ), pPassword );
-    setPass.bindValue( QStringLiteral( ":id" ), 0 );
-
-    if ( !setPass.exec() ) {
-        qWarning() << setPass.lastError();
+    querySetPassword.bindValue( QStringLiteral( ":password" ), pPassword );
+    querySetPassword.bindValue( QStringLiteral( ":id" ), 0 );
+
+    if ( !querySetPassword.exec() ) {
+        qWarning() << querySetPassword.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::setToken( const QString &pToken, uint pExpire )
 {
     transaction();
-    QSqlQuery setToken;
-
-    setToken.prepare( QStringLiteral( "UPDATE user_data "
-                                      "SET token=:token, token_expire=:token_expire WHERE id=:id" ) );
-    setToken.bindValue( QStringLiteral( ":token" ), pToken );
-    setToken.bindValue( QStringLiteral( ":id" ), 0 );
-    setToken.bindValue( QStringLiteral( ":token_expire" ), pExpire );
+    querySetToken.bindValue( QStringLiteral( ":token" ), pToken );
+    querySetToken.bindValue( QStringLiteral( ":id" ), 0 );
+    querySetToken.bindValue( QStringLiteral( ":token_expire" ), pExpire );
 
-    if ( !setToken.exec() ) {
-        qWarning() << setToken.lastError();
+    if ( !querySetToken.exec() ) {
+        qWarning() << querySetToken.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::setUserData( const QString &pUser, const QString &pPass )
 {
     transaction();
-    QSqlQuery setUser;
+    querySetUser.bindValue( ":id", 0 );
+    querySetUser.bindValue( ":password", pPass );
+    querySetUser.bindValue( ":username", pUser );
 
-    setUser.prepare( QStringLiteral( "REPLACE INTO user_data "
-                                     "(id,password,username) VALUES(:id,:password,:username)" ) );
-    setUser.bindValue( ":password", pPass );
-    setUser.bindValue( ":id", 0 );
-    setUser.bindValue( ":username", pUser );
-
-    if ( !setUser.exec() ) {
-        qWarning() << setUser.lastError();
+    if ( !querySetUser.exec() ) {
+        qWarning() << querySetUser.lastError();
+        qWarning() << querySetUser.lastQuery();
     }
 
-    commit();
+    askForcommit();
 }
 
 QString PersistanceLayer::addFileToTemp( const QString &pUrl, const QString &pPath )
@@ -721,75 +746,67 @@ void PersistanceLayer::createFolder( const QString &pPath )
 void PersistanceLayer::setUserId( const QString &pUserId )
 {
     transaction();
-    QSqlQuery setUserId;
-    setUserId.prepare( QStringLiteral( "UPDATE user_data SET user_id=:userId WHERE id=:id" ) );
-    setUserId.bindValue( QStringLiteral( ":id" ), 0 );
-    setUserId.bindValue( QStringLiteral( ":userId" ), pUserId );
+    querySetUserId.bindValue( QStringLiteral( ":id" ), 0 );
+    querySetUserId.bindValue( QStringLiteral( ":userId" ), pUserId );
 
-    if ( !setUserId.exec() ) {
-        qWarning() << setUserId.lastError();
+    if ( !querySetUserId.exec() ) {
+        qWarning() << querySetUserId.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::setCurrentChannel( const QString &pChannelId, const QString &pChannelName )
 {
     transaction();
-    QSqlQuery setChannel;
-    setChannel.prepare( QStringLiteral( "REPLACE INTO current_room"
-                                        "(id,rid,name) VALUES(:id,:rid,:name)" ) );
-    setChannel.bindValue( QStringLiteral( ":id" ), 0 );
-    setChannel.bindValue( QStringLiteral( ":rid" ), pChannelId );
-    setChannel.bindValue( QStringLiteral( ":name" ), pChannelName );
-
-    if ( !setChannel.exec() ) {
-        qWarning() << setChannel.lastError();
+
+    querySetChannel.bindValue( QStringLiteral( ":id" ), 0 );
+    querySetChannel.bindValue( QStringLiteral( ":rid" ), pChannelId );
+    querySetChannel.bindValue( QStringLiteral( ":name" ), pChannelName );
+
+    if ( !querySetChannel.exec() ) {
+        qWarning() << querySetChannel.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::setSetting( const QString &pProperty, const QString &pValue )
 {
     transaction();
-    QSqlQuery setChannel;
-    setChannel.prepare( QStringLiteral( "REPLACE INTO app_settings"
-                                        "(property,value) VALUES(:property,:value)" ) );
-    setChannel.bindValue( QStringLiteral( ":property" ), pProperty );
-    setChannel.bindValue( QStringLiteral( ":value" ), pValue );
-
-    if ( !setChannel.exec() ) {
-        qWarning() << setChannel.lastError();
+
+    querySetSetting.bindValue( QStringLiteral( ":property" ), pProperty );
+    querySetSetting.bindValue( QStringLiteral( ":value" ), pValue );
+
+    if ( !querySetSetting.exec() ) {
+        qWarning() << querySetSetting.lastQuery();
+        qWarning() << querySetSetting.lastError();
     }
 
-    commit();
+    askForcommit();
 
 }
 
 void PersistanceLayer::addChannel( const QString &pId, const QString &pName, const QString &pType, bool pJoined, bool pReadOnly, const QString &pMuted, bool pArchived, bool pBlocked, const QString &pUsername, const QString &pChatPartnerId )
 {
     transaction();
-    QSqlQuery setChannel;
-    setChannel.prepare( QStringLiteral( "REPLACE INTO rooms "
-                                        "(id,name,type,joined,read_only,muted,archived,blocked,username,chat_partner_id) VALUES(:id,:name,:type,:joined,:read_only,:muted,:archived,:blocked,:username,:chat_partner_id)" ) );
-    setChannel.bindValue( QStringLiteral( ":id" ), pId );
-    setChannel.bindValue( QStringLiteral( ":name" ), pName );
-    setChannel.bindValue( QStringLiteral( ":joined" ), pJoined );
-    setChannel.bindValue( QStringLiteral( ":type" ), pType );
-    setChannel.bindValue( QStringLiteral( ":read_only" ), pReadOnly );
-    setChannel.bindValue( QStringLiteral( ":muted" ), pMuted );
-    setChannel.bindValue( QStringLiteral( ":archived" ), pArchived );
-    setChannel.bindValue( QStringLiteral( ":blocked" ), pBlocked );
-    setChannel.bindValue( QStringLiteral( ":username" ), pUsername );
-    setChannel.bindValue( QStringLiteral( ":chat_partner_id" ), pChatPartnerId );
-
-
-    if ( !setChannel.exec() ) {
-        qWarning() << setChannel.lastError();
+    queryAddChannel.bindValue( QStringLiteral( ":id" ), pId );
+    queryAddChannel.bindValue( QStringLiteral( ":name" ), pName );
+    queryAddChannel.bindValue( QStringLiteral( ":joined" ), pJoined );
+    queryAddChannel.bindValue( QStringLiteral( ":type" ), pType );
+    queryAddChannel.bindValue( QStringLiteral( ":read_only" ), pReadOnly );
+    queryAddChannel.bindValue( QStringLiteral( ":muted" ), pMuted );
+    queryAddChannel.bindValue( QStringLiteral( ":archived" ), pArchived );
+    queryAddChannel.bindValue( QStringLiteral( ":blocked" ), pBlocked );
+    queryAddChannel.bindValue( QStringLiteral( ":username" ), pUsername );
+    queryAddChannel.bindValue( QStringLiteral( ":chat_partner_id" ), pChatPartnerId );
+
+
+    if ( !queryAddChannel.exec() ) {
+        qWarning() << queryAddChannel.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::addChannel( const QString &pId, const QString &pName, const QString &pType, bool pJoined, const QString &pUsername, const QString &pMchatPartnerId )
@@ -803,18 +820,15 @@ void PersistanceLayer::addChannel( const QString &pId, const QString &pName, con
 
 void PersistanceLayer::deleteChannel( const QString &pId )
 {
-    QSqlQuery deleteQuery;
-    deleteQuery.prepare( QStringLiteral( "DELETE FROM rooms WHERE id=:id" ) );
-    deleteQuery.bindValue( QStringLiteral( ":id" ), pId );
+    queryDeleteChannel.bindValue( QStringLiteral( ":id" ), pId );
 
-    if ( !deleteQuery.exec() ) {
-        qWarning() << deleteQuery.lastError();
+    if ( !queryDeleteChannel.exec() ) {
+        qWarning() << queryDeleteChannel.lastError();
     } else {
-        deleteQuery.prepare( QStringLiteral( "DELETE FROM messages WHERE rid=:id" ) );
-        deleteQuery.bindValue( QStringLiteral( ":id" ), pId );
+        queryDeleteMessagesFromChannel.bindValue( QStringLiteral( ":id" ), pId );
 
-        if ( !deleteQuery.exec() ) {
-            qWarning() << deleteQuery.lastError();
+        if ( !queryDeleteMessagesFromChannel.exec() ) {
+            qWarning() << queryDeleteMessagesFromChannel.lastError();
         }
     }
 }
@@ -822,24 +836,21 @@ void PersistanceLayer::deleteChannel( const QString &pId )
 void PersistanceLayer::addMessage( const QString &pId, const QString &pRid, const QString &pAuthor, qint64 pTs, const QString &pJson, const QString &pUserId )
 {
     transaction();
-    QSqlQuery addMessage( mDb );
-    addMessage.prepare( QStringLiteral( "REPLACE INTO messages "
-                                        "(id,rid,author,ts,json,read, user_id) VALUES (:id,:rid,:author,:ts,:json,0,:user_id)" ) );
-    addMessage.bindValue( QStringLiteral( ":id" ), pId );
-    addMessage.bindValue( QStringLiteral( ":rid" ), pRid );
-    addMessage.bindValue( QStringLiteral( ":author" ), pAuthor );
-    addMessage.bindValue( QStringLiteral( ":ts" ), pTs );
-    addMessage.bindValue( QStringLiteral( ":json" ), pJson );
-    addMessage.bindValue( QStringLiteral( ":user_id" ), pUserId );
-
-    if ( !addMessage.exec() ) {
+    queryAddMessage.bindValue( QStringLiteral( ":id" ), pId );
+    queryAddMessage.bindValue( QStringLiteral( ":rid" ), pRid );
+    queryAddMessage.bindValue( QStringLiteral( ":author" ), pAuthor );
+    queryAddMessage.bindValue( QStringLiteral( ":ts" ), pTs );
+    queryAddMessage.bindValue( QStringLiteral( ":json" ), pJson );
+    queryAddMessage.bindValue( QStringLiteral( ":user_id" ), pUserId );
+
+    if ( !queryAddMessage.exec() ) {
         qWarning() << "id: " << pId << " rid: " << pRid << " author: " << pAuthor << " ts: " << pTs << " json: " << pJson << "userId: " << pUserId;
-        qWarning() << addMessage.lastQuery();
-        qWarning() << addMessage.executedQuery();
-        qWarning() << addMessage.lastError();
+        qWarning() << queryAddMessage.lastQuery();
+        qWarning() << queryAddMessage.executedQuery();
+        qWarning() << queryAddMessage.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::addFileCacheEntry( const QString &pUrl, const QString &pPath )
@@ -849,18 +860,16 @@ void PersistanceLayer::addFileCacheEntry( const QString &pUrl, const QString &pP
     qDebug() << pPath;
 
     QDateTime dateTime = QDateTime::currentDateTime();
-    QSqlQuery addCacheEntry;
-    addCacheEntry.prepare( QStringLiteral( "REPLACE INTO file_cache (url,path,ts)"
-                                           " VALUES (:url,:path,:ts)" ) );
-    addCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl );
-    addCacheEntry.bindValue( QStringLiteral( ":path" ), pPath );
-    addCacheEntry.bindValue( QStringLiteral( ":ts" ), dateTime.toTime_t() );
-
-    if ( !addCacheEntry.exec() ) {
-        qWarning() << addCacheEntry.lastError();
+
+    queryAddCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl );
+    queryAddCacheEntry.bindValue( QStringLiteral( ":path" ), pPath );
+    queryAddCacheEntry.bindValue( QStringLiteral( ":ts" ), dateTime.toTime_t() );
+
+    if ( !queryAddCacheEntry.exec() ) {
+        qWarning() << queryAddCacheEntry.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory )
@@ -875,52 +884,45 @@ void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath
 void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory, const QString &pUnicode, int pOrder )
 {
     transaction();
-    QSqlQuery addCustomEmojiQuery;
-    addCustomEmojiQuery.prepare( QStringLiteral( "REPLACE INTO custom_emojis (id,file,html,unicode,category,sort_order)"
-                                 " VALUES (:id,:file,:html,:unicode,:category,:sort_order)" ) );
-    addCustomEmojiQuery.bindValue( QStringLiteral( ":id" ), pTag );
-    addCustomEmojiQuery.bindValue( QStringLiteral( ":file" ), pPath );
-    addCustomEmojiQuery.bindValue( QStringLiteral( ":html" ), pHtml );
-    addCustomEmojiQuery.bindValue( QStringLiteral( ":unicode" ), pUnicode );
-    addCustomEmojiQuery.bindValue( QStringLiteral( ":category" ), pCategory );
-    addCustomEmojiQuery.bindValue( QStringLiteral( ":sort_order" ), pOrder );
-
-    if ( !addCustomEmojiQuery.exec() ) {
-        qWarning() << addCustomEmojiQuery.lastError();
+    queryAddEmoji.bindValue( QStringLiteral( ":id" ), pTag );
+    queryAddEmoji.bindValue( QStringLiteral( ":file" ), pPath );
+    queryAddEmoji.bindValue( QStringLiteral( ":html" ), pHtml );
+    queryAddEmoji.bindValue( QStringLiteral( ":unicode" ), pUnicode );
+    queryAddEmoji.bindValue( QStringLiteral( ":category" ), pCategory );
+    queryAddEmoji.bindValue( QStringLiteral( ":sort_order" ), pOrder );
+
+    if ( !queryAddEmoji.exec() ) {
+        qWarning() << queryAddEmoji.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 void PersistanceLayer::addUserToBlockList( const QString &pUserId, const QString &pUsername )
 {
     transaction();
-    QSqlQuery addUserQuery;
-    addUserQuery.prepare( QStringLiteral( "INSERT INO blocked_users(id, author) VALUES(:id,:author)" ) );
-    addUserQuery.bindValue( ":id", pUserId );
-    addUserQuery.bindValue( ":author", pUsername );
+    queryAddUser.bindValue( ":id", pUserId );
+    queryAddUser.bindValue( ":author", pUsername );
 
-    if ( !addUserQuery.exec() ) {
-        qWarning() << addUserQuery.lastError();
+    if ( !queryAddUser.exec() ) {
+        qWarning() << queryAddUser.lastError();
     }
 
-    commit();
+    askForcommit();
 
 }
 
 
 QHash<QString, QString> PersistanceLayer::getMessageByid( const QString &pId )
 {
-    QSqlQuery message;
-    message.prepare( QStringLiteral( "SELECT * FROM messages LEFT JOIN blocked_users ON (messages.user_id=blocked_users.user_id) WHERE blocked_users.user_id IS NULL AND id=:id" ) );
-    message.bindValue( QStringLiteral( ":id" ), pId );
+    queryGetMessageByRid.bindValue( QStringLiteral( ":id" ), pId );
     QHash<QString, QString> row;
 
-    if ( !message.exec() ) {
-        qWarning() << message.lastError();
+    if ( !queryGetMessageByRid.exec() ) {
+        qWarning() << queryGetMessageByRid.lastError();
     } else {
 
-        QSqlRecord rec = message.record();
+        QSqlRecord rec = queryGetMessageByRid.record();
         int idCol = rec.indexOf( QStringLiteral( "id" ) );
         int ridCol = rec.indexOf( QStringLiteral( "rid" ) );
         int authorCol = rec.indexOf( QStringLiteral( "author" ) );
@@ -928,36 +930,35 @@ QHash<QString, QString> PersistanceLayer::getMessageByid( const QString &pId )
         int messageCol = rec.indexOf( QStringLiteral( "message" ) );
         int typeCol = rec.indexOf( QStringLiteral( "type" ) );
 
-        while ( message.next() ) {
-            row[QStringLiteral( "id" )] = message.value( idCol ).toString();
-            row[QStringLiteral( "rid" )] = message.value( ridCol ).toString();
-            row[QStringLiteral( "author" )] = message.value( authorCol ).toString();
-            row[QStringLiteral( "message" )] = message.value( messageCol ).toString();
-            row[QStringLiteral( "ts" )] = message.value( tsCol ).toString();
-            row[QStringLiteral( "type" )] = message.value( typeCol ).toString();
+        while ( queryGetMessageByRid.next() ) {
+            row[QStringLiteral( "id" )] = queryGetMessageByRid.value( idCol ).toString();
+            row[QStringLiteral( "rid" )] = queryGetMessageByRid.value( ridCol ).toString();
+            row[QStringLiteral( "author" )] = queryGetMessageByRid.value( authorCol ).toString();
+            row[QStringLiteral( "message" )] = queryGetMessageByRid.value( messageCol ).toString();
+            row[QStringLiteral( "ts" )] = queryGetMessageByRid.value( tsCol ).toString();
+            row[QStringLiteral( "type" )] = queryGetMessageByRid.value( typeCol ).toString();
         }
     }
 
+    queryGetMessageByRid.finish();
     return row;
 }
 
 
 QString PersistanceLayer::getUserName()
 {
-    QSqlQuery getName;
-    getName.prepare( QStringLiteral( "SELECT username FROM user_data WHERE id=0" ) );
 
     QString name = "";
 
-    if ( !getName.exec() ) {
-        qWarning() << getName.lastError();
+    if ( !queryGetName.exec() ) {
+        qWarning() << queryGetName.lastError();
     } else {
 
-        QSqlRecord rec = getName.record();
+        QSqlRecord rec = queryGetName.record();
         int nameCol = rec.indexOf( QStringLiteral( "username" ) );
 
-        while ( getName.next() ) {
-            name = getName.value( nameCol ).toString();
+        while ( queryGetName.next() ) {
+            name = queryGetName.value( nameCol ).toString();
         }
     }
 
@@ -966,111 +967,105 @@ QString PersistanceLayer::getUserName()
 
 std::tuple<QString, QString> PersistanceLayer::getCurrentChannel()
 {
-    QSqlQuery getChannel;
-    getChannel.prepare( QStringLiteral( "SELECT * FROM current_room WHERE id=0" ) );
     QString id;
     QString name;
 
-    if ( !getChannel.exec() ) {
-        qWarning() << getChannel.lastError();
+    if ( !queryGetCurrentChannel.exec() ) {
+        qWarning() << queryGetCurrentChannel.lastError();
     } else {
-        while ( getChannel.next() ) {
-            id = getChannel.value( QStringLiteral( "rid" ) ).toString();
-            name = getChannel.value( QStringLiteral( "name" ) ).toString();
+        while ( queryGetCurrentChannel.next() ) {
+            id = queryGetCurrentChannel.value( QStringLiteral( "rid" ) ).toString();
+            name = queryGetCurrentChannel.value( QStringLiteral( "name" ) ).toString();
         }
     }
 
+    queryGetCurrentChannel.finish();
     return std::tuple<QString, QString>( id, name );
 }
 
 QString PersistanceLayer::getPassword()
 {
-    QSqlQuery getPass;
-    getPass.prepare( QStringLiteral( "SELECT password FROM user_data WHERE id=0" ) );
     QString pass = "";
 
-    if ( !getPass.exec() ) {
-        qWarning() << getPass.lastError();
+    if ( !queryGetPass.exec() ) {
+        qWarning() << queryGetPass.lastError();
     } else {
 
-        QSqlRecord rec = getPass.record();
+        QSqlRecord rec = queryGetPass.record();
         int nameCol = rec.indexOf( QStringLiteral( "password" ) );
 
-        while ( getPass.next() ) {
-            pass = getPass.value( nameCol ).toString();
+        while ( queryGetPass.next() ) {
+            pass = queryGetPass.value( nameCol ).toString();
         }
     }
 
+    queryGetPass.finish();
     return pass;
 }
 
 QPair<QString, uint> PersistanceLayer::getToken()
 {
-    QSqlQuery getToken;
-    getToken.prepare( QStringLiteral( "SELECT token, token_expire FROM user_data WHERE id=0" ) );
     // getToken.bindValue( ":id", 0 );
     QPair<QString, uint> token;
 
-    if ( !getToken.exec() ) {
-        qWarning() << getToken.lastError();
+    if ( !queryGetToken.exec() ) {
+        qDebug() << queryGetToken.lastError();
     } else {
-        QSqlRecord rec = getToken.record();
+        QSqlRecord rec = queryGetToken.record();
         int tokenCol = rec.indexOf( QStringLiteral( "token" ) );
         int expireCol = rec.indexOf( QStringLiteral( "token_expire" ) );
 
-        while ( getToken.next() ) {
-            token.first = getToken.value( tokenCol ).toString();
-            token.second = getToken.value( expireCol ).toUInt();
+        while ( queryGetToken.next() ) {
+            token.first = queryGetToken.value( tokenCol ).toString();
+            token.second = queryGetToken.value( expireCol ).toUInt();
         }
     }
 
+    queryGetToken.finish();
     return token;
 }
 
 QString PersistanceLayer::getUserId()
 {
-    QSqlQuery getUserId;
-    getUserId.prepare( "SELECT id,user_id FROM user_data WHERE id=0" );
     //getUserId.addBindValue( ":id", 0 );
     QString userId;
 
-    if ( !getUserId.exec() ) {
-        qWarning() << "userid error" << getUserId.lastError();
+    if ( !queryGetUserId.exec() ) {
+        qWarning() << "userid error" << queryGetUserId.lastError();
     } else {
-        QSqlRecord rec = getUserId.record();
+        QSqlRecord rec = queryGetUserId.record();
         int userIdCol = rec.indexOf( QStringLiteral( "user_id" ) );
 
-        while ( getUserId.next() ) {
-            userId = getUserId.value( userIdCol ).toString();
+        while ( queryGetUserId.next() ) {
+            userId = queryGetUserId.value( userIdCol ).toString();
         }
     }
 
+    queryGetUserId.finish();
     return userId;
 }
 
 QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid )
 {
-    QSqlQuery messages;
-    messages.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid ORDER BY ts DESC LIMIT 20" ) );
-    messages.bindValue( QStringLiteral( ":rid" ), pRid );
+    queryGetMessagesByRid.bindValue( QStringLiteral( ":rid" ), pRid );
 
     QList<QJsonObject> rows;
     rows.reserve( 50 );
 
-    if ( !messages.exec() ) {
+    if ( !queryGetMessagesByRid.exec() ) {
         qWarning() << QStringLiteral( "request room with rid: " ) << pRid;
-        qWarning() << messages.lastError();
+        qWarning() << queryGetMessagesByRid.lastError();
     } else {
 
-        QSqlRecord rec = messages.record();
+        QSqlRecord rec = queryGetMessagesByRid.record();
         int jsonCol = rec.indexOf( QStringLiteral( "json" ) );
         int readCol = rec.indexOf( QStringLiteral( "read" ) );
 
 
-        while ( messages.next() ) {
+        while ( queryGetMessagesByRid.next() ) {
             //QHash<QString,QJsonObject> entry;
-            QString json = messages.value( jsonCol ).toString();
-            bool read =  messages.value( readCol ).toBool();
+            QString json = queryGetMessagesByRid.value( jsonCol ).toString();
+            bool read =  queryGetMessagesByRid.value( readCol ).toBool();
             QJsonDocument doc = QJsonDocument::fromJson( json.toUtf8() );
             QJsonObject object = doc.object();
             object[QStringLiteral( "read" )] = read;
@@ -1081,33 +1076,32 @@ QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid )
         }
     }
 
+    queryGetMessagesByRid.finish();
     return rows;
 }
 
 QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid, qint64 pFrom, qint64 pTo )
 {
-    QSqlQuery messages;
-    messages.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from AND ts>=:to ORDER BY ts DESC LIMIT 50" ) );
-    messages.bindValue( QStringLiteral( ":rid" ), pRid );
-    messages.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom / 1000 ) );
-    messages.bindValue( QStringLiteral( ":to" ), static_cast<qint64>( pTo / 1000 ) );
+    queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":rid" ), pRid );
+    queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom / 1000 ) );
+    queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":to" ), static_cast<qint64>( pTo / 1000 ) );
 
     QList<QJsonObject> rows;
     rows.reserve( 50 );
 
-    if ( !messages.exec() ) {
+    if ( !queryGetMessageByRidAndRange.exec() ) {
         qWarning() << "request room with rid: " << pRid;
-        qWarning() << messages.lastError();
+        qWarning() << queryGetMessageByRidAndRange.lastError();
     } else {
 
-        QSqlRecord rec = messages.record();
+        QSqlRecord rec = queryGetMessageByRidAndRange.record();
         int jsonCol = rec.indexOf( QStringLiteral( "json" ) );
         int readCol = rec.indexOf( QStringLiteral( "read" ) );
 
 
-        while ( messages.next() ) {
-            QString json = messages.value( jsonCol ).toString();
-            bool read =  messages.value( readCol ).toBool();
+        while ( queryGetMessageByRidAndRange.next() ) {
+            QString json = queryGetMessageByRidAndRange.value( jsonCol ).toString();
+            bool read =  queryGetMessageByRidAndRange.value( readCol ).toBool();
             QJsonDocument doc = QJsonDocument::fromJson( json.toUtf8() );
             QJsonObject object = doc.object();
             object[QStringLiteral( "read" )] = read;
@@ -1118,34 +1112,33 @@ QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid, qint
         }
     }
 
+    queryGetMessageByRidAndRange.finish();
     return rows;
 }
 
 QList<QJsonObject > PersistanceLayer::getMessagesByRid( const QString &pRid, qint64 pFrom, int pLimit )
 {
-    QSqlQuery messages;
-    messages.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from ORDER BY ts DESC LIMIT :limit" ) );
-    messages.bindValue( QStringLiteral( ":rid" ), pRid );
-    messages.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom ) );
-    messages.bindValue( QStringLiteral( ":limit" ), pLimit );
+    queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":rid" ), pRid );
+    queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom ) );
+    queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":limit" ), pLimit );
 
     QList<QJsonObject > rows;
     rows.reserve( 50 );
 
-    if ( !messages.exec() ) {
+    if ( !queryGetMessagesByRidLimit.exec() ) {
         qWarning() << "request room with rid: " << pRid;
-        qWarning() << messages.lastError();
+        qWarning() << queryGetMessagesByRidLimit.lastError();
     } else {
 
-        QSqlRecord rec = messages.record();
+        QSqlRecord rec = queryGetMessagesByRidLimit.record();
         int jsonCol = rec.indexOf( QStringLiteral( "json" ) );
         int readCol = rec.indexOf( QStringLiteral( "read" ) );
 
 
-        while ( messages.next() ) {
+        while ( queryGetMessagesByRidLimit.next() ) {
             // QHash<QString,QJsonObject> entry;
-            QString json = messages.value( jsonCol ).toString();
-            bool read =  messages.value( readCol ).toBool();
+            QString json = queryGetMessagesByRidLimit.value( jsonCol ).toString();
+            bool read =  queryGetMessagesByRidLimit.value( readCol ).toBool();
             QJsonDocument doc = QJsonDocument::fromJson( json.toUtf8() );
             QJsonObject object = doc.object();
 
@@ -1161,46 +1154,44 @@ QList<QJsonObject > PersistanceLayer::getMessagesByRid( const QString &pRid, qin
         }
     }
 
+    queryGetMessagesByRidLimit.finish();
     return rows;
 }
 
 QList<QPair<QString, QString >> PersistanceLayer::getListOfBlockedUsers()
 {
-    QSqlQuery usersQuery;
-    usersQuery.prepare( QStringLiteral( "SELECT * FROM blocked_users" ) );
     QList<QPair<QString, QString >> retList;
 
-    if ( !usersQuery.exec() ) {
+    if ( !queryGetBlockedUsers.exec() ) {
         qWarning() << "getList of blocked users ";
-        qWarning() << usersQuery.lastError();
+        qWarning() << queryGetBlockedUsers.lastError();
     } else {
-        QSqlRecord rec = usersQuery.record();
+        QSqlRecord rec = queryGetBlockedUsers.record();
         int idCol = rec.indexOf( "id" );
         int nameCol = rec.indexOf( "author" );
 
-        while ( usersQuery.next() ) {
+        while ( queryGetBlockedUsers.next() ) {
             QPair<QString, QString> pair;
-            pair.first = usersQuery.value( idCol ).String;
-            pair.second = usersQuery.value( nameCol ).String;
+            pair.first = queryGetBlockedUsers.value( idCol ).String;
+            pair.second = queryGetBlockedUsers.value( nameCol ).String;
             retList.append( pair );
         }
     }
 
+    queryGetBlockedUsers.finish();
     return retList;
 }
 
 
 QList<QVariantHash> PersistanceLayer::getChannels( )
 {
-    QSqlQuery rooms;
-    rooms.prepare( QStringLiteral( "SELECT * FROM rooms LEFT JOIN (SELECT DISTINCT rid FROM messages ORDER BY ts DESC) AS sub ON rooms.id = sub.rid " ) );
     QList<QVariantHash> roomsList;
     roomsList.reserve( 100 );
 
-    if ( !rooms.exec() ) {
-        qWarning() << rooms.lastError();
+    if ( !queryGetChannels.exec() ) {
+        qWarning() << queryGetChannels.lastError();
     } else {
-        QSqlRecord rec = rooms.record();
+        QSqlRecord rec = queryGetChannels.record();
         int idCol = rec.indexOf( QStringLiteral( "id" ) );
         int nameCol = rec.indexOf( QStringLiteral( "name" ) );
         int joinedCol = rec.indexOf( QStringLiteral( "joined" ) );
@@ -1213,40 +1204,39 @@ QList<QVariantHash> PersistanceLayer::getChannels( )
         int chatPartnerIdCol = rec.indexOf( QStringLiteral( "chat_partner_id" ) );
 
 
-        while ( rooms.next() ) {
+        while ( queryGetChannels.next() ) {
             QVariantHash roomsHash;
-            QString muted = rooms.value( mutedCol ).toString();
-            roomsHash[QStringLiteral( "id" )] = rooms.value( idCol ).toString();
-            roomsHash[QStringLiteral( "name" )] = rooms.value( nameCol ).toString();
-            roomsHash[QStringLiteral( "joined" )] = rooms.value( joinedCol ).toBool();
-            roomsHash[QStringLiteral( "type" )] = rooms.value( typeCol ).toString();
-            roomsHash[QStringLiteral( "readOnly" )] = rooms.value( readOnlyCol ).toBool();
+            QString muted = queryGetChannels.value( mutedCol ).toString();
+            roomsHash[QStringLiteral( "id" )] = queryGetChannels.value( idCol ).toString();
+            roomsHash[QStringLiteral( "name" )] = queryGetChannels.value( nameCol ).toString();
+            roomsHash[QStringLiteral( "joined" )] = queryGetChannels.value( joinedCol ).toBool();
+            roomsHash[QStringLiteral( "type" )] = queryGetChannels.value( typeCol ).toString();
+            roomsHash[QStringLiteral( "readOnly" )] = queryGetChannels.value( readOnlyCol ).toBool();
             roomsHash[QStringLiteral( "muted" )] = muted;
             roomsHash[QStringLiteral( "list" )] = muted.split( ',' );
-            roomsHash[QStringLiteral( "archived" )] = rooms.value( archivedCol ).toBool();
-            roomsHash[QStringLiteral( "blocked" )] = rooms.value( blocked ).toBool();
-            roomsHash[QStringLiteral( "username" )] = rooms.value( usernameCol ).toString();
-            roomsHash[QStringLiteral( "chatPartnerId" )] = rooms.value( chatPartnerIdCol ).toString();
+            roomsHash[QStringLiteral( "archived" )] = queryGetChannels.value( archivedCol ).toBool();
+            roomsHash[QStringLiteral( "blocked" )] = queryGetChannels.value( blocked ).toBool();
+            roomsHash[QStringLiteral( "username" )] = queryGetChannels.value( usernameCol ).toString();
+            roomsHash[QStringLiteral( "chatPartnerId" )] = queryGetChannels.value( chatPartnerIdCol ).toString();
 
             roomsList.append( roomsHash );
         }
     }
 
+    queryGetChannels.finish();
     return roomsList;
 }
 
 QList< QHash<QString, QString > > PersistanceLayer::getCustomEmojis()
 {
-    QSqlQuery emojiQuery;
-    emojiQuery.prepare( QStringLiteral( "SELECT id,file,html,category,unicode,sort_order FROM custom_emojis ORDER BY sort_order ASC" ) );
     QList<QHash<QString, QString> > returnList;
     returnList.reserve( 3000 );
 
-    if ( !emojiQuery.exec() ) {
-        qWarning() << emojiQuery.lastError();
+    if ( !queryGetEmojies.exec() ) {
+        qWarning() << queryGetEmojies.lastError();
     } else {
 
-        QSqlRecord rec = emojiQuery.record();
+        QSqlRecord rec = queryGetEmojies.record();
 
         int idCol = rec.indexOf( QStringLiteral( "id" ) );
         int fileCol = rec.indexOf( QStringLiteral( "file" ) );
@@ -1255,38 +1245,37 @@ QList< QHash<QString, QString > > PersistanceLayer::getCustomEmojis()
         int unicodeCol = rec.indexOf( QStringLiteral( "unicode" ) );
         int orderCol = rec.indexOf( QStringLiteral( "sort_order" ) );
 
-        while ( emojiQuery.next() ) {
+        while ( queryGetEmojies.next() ) {
             QHash<QString, QString> entry;
-            entry[QStringLiteral( "id" )] = emojiQuery.value( idCol ).toString();
-            entry[QStringLiteral( "file" )] = emojiQuery.value( fileCol ).toString();
-            entry[QStringLiteral( "html" )] = emojiQuery.value( htmlCol ).toString();
-            entry[QStringLiteral( "category" )] = emojiQuery.value( catCol ).toString();
-            entry[QStringLiteral( "unicode" )] = emojiQuery.value( unicodeCol ).toString();
-            entry[QStringLiteral( "sort_order" )] = emojiQuery.value( orderCol ).toString();
+            entry[QStringLiteral( "id" )] = queryGetEmojies.value( idCol ).toString();
+            entry[QStringLiteral( "file" )] = queryGetEmojies.value( fileCol ).toString();
+            entry[QStringLiteral( "html" )] = queryGetEmojies.value( htmlCol ).toString();
+            entry[QStringLiteral( "category" )] = queryGetEmojies.value( catCol ).toString();
+            entry[QStringLiteral( "unicode" )] = queryGetEmojies.value( unicodeCol ).toString();
+            entry[QStringLiteral( "sort_order" )] = queryGetEmojies.value( orderCol ).toString();
 
             returnList.append( entry );
         }
     }
 
+    queryGetEmojies.finish();
     return returnList;
 }
 
 QString PersistanceLayer::getFileCacheEntry( const QString &pUrl )
 {
-    QSqlQuery cacheEntry;
-    cacheEntry.prepare( QStringLiteral( "SELECT path FROM file_cache WHERE url=:url" ) );
-    cacheEntry.bindValue( QStringLiteral( ":url" ), pUrl );
+    queryGetFileCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl );
     QString returnString = "";
 
-    if ( !cacheEntry.exec() ) {
-        qWarning() << cacheEntry.lastError();
+    if ( !queryGetFileCacheEntry.exec() ) {
+        qWarning() << queryGetFileCacheEntry.lastError();
     } else {
 
-        QSqlRecord rec = cacheEntry.record();
+        QSqlRecord rec = queryGetFileCacheEntry.record();
         int pathCol = rec.indexOf( QStringLiteral( "path" ) );
 
-        while ( cacheEntry.next() ) {
-            returnString = cacheEntry.value( pathCol ).toString();
+        while ( queryGetFileCacheEntry.next() ) {
+            returnString = queryGetFileCacheEntry.value( pathCol ).toString();
         }
 
         if ( returnString != "" ) {
@@ -1299,28 +1288,28 @@ QString PersistanceLayer::getFileCacheEntry( const QString &pUrl )
         }
     }
 
+    queryGetFileCacheEntry.finish();
     return returnString;
 }
 
 QString PersistanceLayer::getSetting( const QString &pProperty )
 {
-    QSqlQuery settingsEntry;
-    settingsEntry.prepare( QStringLiteral( "SELECT property,value FROM app_settings WHERE property=:property" ) );
-    settingsEntry.bindValue( QStringLiteral( ":property" ), pProperty );
+    queryGetSetting.bindValue( QStringLiteral( ":property" ), pProperty );
     QString returnString = "";
 
-    if ( !settingsEntry.exec() ) {
-        qWarning() << settingsEntry.lastError();
+    if ( !queryGetSetting.exec() ) {
+        qWarning() << queryGetSetting.lastError();
     } else {
-        QSqlRecord rec = settingsEntry.record();
+        QSqlRecord rec = queryGetSetting.record();
 
         int valueClol = rec.indexOf( QStringLiteral( "value" ) );
 
-        while ( settingsEntry.next() ) {
-            returnString = settingsEntry.value( valueClol ).toString();
+        while ( queryGetSetting.next() ) {
+            returnString = queryGetSetting.value( valueClol ).toString();
         }
     }
 
+    queryGetSetting.finish();
     return returnString;
 }
 
@@ -1345,15 +1334,13 @@ void PersistanceLayer::removeFileCacheEntry( const QString &pUrl, const QString
         }
     }
 
-    QSqlQuery cacheEntry;
-    cacheEntry.prepare( QStringLiteral( "DELETE FROM file_cache WHERE url=:url" ) );
-    cacheEntry.bindValue( QStringLiteral( ":url" ), pUrl );
+    queryRemoveFileCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl );
 
-    if ( !cacheEntry.exec() ) {
-        qWarning() << cacheEntry.lastError();
+    if ( !queryRemoveFileCacheEntry.exec() ) {
+        qWarning() << queryRemoveFileCacheEntry.lastError();
     }
 
-    commit();
+    askForcommit();
 }
 
 
@@ -1451,12 +1438,12 @@ void PersistanceLayer::init()
             throw std::runtime_error( mDb.lastError().text().toStdString() + "file used:" + filePath.toStdString() );
         }
 
-        commitTimer.setInterval( 3000 );
-        commitTimer.start();
+        // commitTimer.setInterval( 10000 );
         connect( &commitTimer, &QTimer::timeout, [&]() {
             commit();
             commitTimer.start();
         } );
+        //  commitTimer.start();
         mDbReady = true;
         initShema();
         emit( ready() );
@@ -1467,7 +1454,52 @@ void PersistanceLayer::init()
     }
 }
 
+void PersistanceLayer::initQueries()
+{
+    querySetUsername.prepare( QStringLiteral( "UPDATE user_data "
+                              "SET username=:username WHERE id=:id" ) );
+    querySetPassword.prepare( QStringLiteral( "UPDATE user_data "
+                              "SET password=:password WHERE id=:id" ) );
+    querySetToken.prepare( QStringLiteral( "UPDATE user_data "
+                                           "SET token=:token, token_expire=:token_expire WHERE id=:id" ) );
+    querySetUser.prepare( QStringLiteral( "REPLACE INTO user_data "
+                                          "(id,password,username) VALUES(:id,:password,:username)" ) );
+    querySetUserId.prepare( QStringLiteral( "UPDATE user_data SET user_id=:userId WHERE id=:id" ) );
+
+    querySetChannel.prepare( QStringLiteral( "REPLACE INTO current_room"
+                             " (id,rid,name) VALUES(:id,:rid,:name)" ) );
+    querySetSetting.prepare( QStringLiteral( "REPLACE INTO app_settings"
+                             " (property,value) VALUES(:property,:value)" ) );
+    queryAddChannel.prepare( QStringLiteral( "REPLACE INTO rooms "
+                             "(id,name,type,joined,read_only,muted,archived,blocked,username,chat_partner_id) VALUES(:id,:name,:type,:joined,:read_only,:muted,:archived,:blocked,:username,:chat_partner_id)" ) );
+    queryDeleteChannel.prepare( QStringLiteral( "DELETE FROM rooms WHERE id=:id" ) );
+    queryDeleteMessagesFromChannel.prepare( QStringLiteral( "DELETE FROM messages WHERE rid=:id" ) );
+    queryAddMessage.prepare( QStringLiteral( "REPLACE INTO messages "
+                             "(id,rid,author,ts,json,read, user_id) VALUES (:id,:rid,:author,:ts,:json,0,:user_id)" ) );
+    queryAddCacheEntry.prepare( QStringLiteral( "REPLACE INTO file_cache (url,path,ts)"
+                                " VALUES (:url,:path,:ts)" ) );
+    queryAddEmoji.prepare( QStringLiteral( "REPLACE INTO custom_emojis (id,file,html,unicode,category,sort_order)"
+                                           " VALUES (:id,:file,:html,:unicode,:category,:sort_order)" ) );
+    queryAddUser.prepare( QStringLiteral( "INSERT INO blocked_users(id, author) VALUES(:id,:author)" ) );
+    queryGetMessageByRid.prepare( QStringLiteral( "SELECT * FROM messages LEFT JOIN blocked_users ON (messages.user_id=blocked_users.user_id) WHERE blocked_users.user_id IS NULL AND id=:id" ) );
+    queryGetName.prepare( QStringLiteral( "SELECT username FROM user_data WHERE id=0" ) );
+    queryGetCurrentChannel.prepare( QStringLiteral( "SELECT * FROM current_room WHERE id=0" ) );
+    queryGetPass.prepare( QStringLiteral( "SELECT password FROM user_data WHERE id=0" ) );
+    queryGetToken.prepare( QStringLiteral( "SELECT token, token_expire FROM user_data WHERE id=0" ) );
+    queryGetUserId.prepare( "SELECT id,user_id FROM user_data WHERE id=0" );
+    queryGetMessagesByRid.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid ORDER BY ts DESC LIMIT 20" ) );
+    queryGetMessageByRidAndRange.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from AND ts>=:to ORDER BY ts DESC LIMIT 50" ) );
+    queryGetMessagesByRidLimit.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from ORDER BY ts DESC LIMIT :limit" ) );
+    queryGetBlockedUsers.prepare( QStringLiteral( "SELECT * FROM blocked_users" ) );
+    queryGetChannels.prepare( QStringLiteral( "SELECT * FROM rooms LEFT JOIN (SELECT DISTINCT rid FROM messages ORDER BY ts DESC) AS sub ON rooms.id = sub.rid " ) );
+    queryGetEmojies.prepare( QStringLiteral( "SELECT id,file,html,category,unicode,sort_order FROM custom_emojis ORDER BY sort_order ASC" ) );
+    queryGetFileCacheEntry.prepare( QStringLiteral( "SELECT path FROM file_cache WHERE url=:url" ) );
+    queryGetSetting.prepare( QStringLiteral( "SELECT property,value FROM app_settings WHERE property=:property" ) );
+    queryRemoveFileCacheEntry.prepare( QStringLiteral( "DELETE FROM file_cache WHERE url=:url" ) );
+
+}
+
 void PersistanceLayer::close()
 {
-    delete persistanceLayer;
+    persistanceLayer->deleteLater();
 }
diff --git a/persistancelayer.h b/persistancelayer.h
index f1b9186..bf107ed 100755
--- a/persistancelayer.h
+++ b/persistancelayer.h
@@ -5,6 +5,7 @@
 #include <QObject>
 #include <QMetaObject>
 #include <QtSql/QSqlDatabase>
+#include <QtSql/QSqlQuery>
 #include <QFile>
 #include <QMimeDatabase>
 #include <QMimeType>
@@ -48,6 +49,7 @@ class PersistanceLayer : public QObject
         void addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory, const QString &pUnicode );
         void addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory, const QString &pUnicode, int pOrder );
         void addUserToBlockList( const QString &pUserId, const QString &pUsername );
+        void close();
 
     public:
 
@@ -83,7 +85,7 @@ class PersistanceLayer : public QObject
         void removeFileCacheEntry( const QString &pUrl, const QString &pPath );
 
         void transaction( void );
-        void commit( void );
+        void askForcommit( void );
         void wipeDb( void );
 
         bool transactionActive = false;
@@ -91,19 +93,54 @@ class PersistanceLayer : public QObject
         ~PersistanceLayer();
 
         void init();
-        void close();
         bool mDbReady = false;
 
     private:
+        void commit( void );
         PersistanceLayer() {}
         QSqlDatabase mDb{ QSqlDatabase::addDatabase( "QSQLITE" )};
         QMimeDatabase mMimeDb;
         QTimer commitTimer;
+        QMutex commitMutex;
         void initShema();
-
+        void initQueries();
         void upgradeSchema();
 
         int mCommitCounter = 0;
+        int mTransactionCounter = 0;
+
+
+        QSqlQuery querySetUsername;
+        QSqlQuery querySetPassword;
+        QSqlQuery querySetToken;
+        QSqlQuery querySetUser;
+        QSqlQuery querySetUserId;
+        QSqlQuery querySetChannel;
+        QSqlQuery querySetSetting;
+        QSqlQuery queryAddChannel;
+        QSqlQuery queryDeleteChannel;
+        QSqlQuery queryDeleteMessagesFromChannel;
+        QSqlQuery queryAddMessage;
+        QSqlQuery queryAddCacheEntry;
+        QSqlQuery queryAddEmoji;
+        QSqlQuery queryAddUser;
+        QSqlQuery queryGetMessageByRid;
+        QSqlQuery queryGetName;
+        QSqlQuery queryGetCurrentChannel;
+        QSqlQuery queryGetPass;
+        QSqlQuery queryGetToken;
+        QSqlQuery queryGetUserId;
+        QSqlQuery queryGetMessagesByRid;
+        QSqlQuery queryGetMessageByRidAndRange;
+        QSqlQuery queryGetMessagesByRidLimit;
+        QSqlQuery queryGetBlockedUsers;
+        QSqlQuery queryGetChannels;
+        QSqlQuery queryGetEmojies;
+        QSqlQuery queryGetFileCacheEntry;
+        QSqlQuery queryGetSetting;
+        QSqlQuery queryRemoveFileCacheEntry;
+
+
 
     signals:
         void userDataChanged();
diff --git a/rocketchat.cpp b/rocketchat.cpp
index 1c11283..1c15565 100755
--- a/rocketchat.cpp
+++ b/rocketchat.cpp
@@ -98,15 +98,17 @@ RocketChat::~RocketChat()
         mServerThread.quit();
     } else {
         for ( auto element : mServerMap ) {
-            connect( element, &RocketChatServerData::destroyed, [ = ]() {
+            connect( element, &RocketChatServerData::destroyed, [ & ]() {
                 destructCounter--;
 
                 if ( !destructCounter ) {
-                    mServerThread.quit();
+                    connect( PersistanceLayer::instance(), &PersistanceLayer::destroyed, [&]() {
+                        mServerThread.quit();
+                    } );
+                    QMetaObject::invokeMethod( PersistanceLayer::instance(),  "close" );
                 }
             } );
-
-            element->deleteLater();
+            QMetaObject::invokeMethod( element,  "deleteLater" );
         }
     }
 
@@ -883,7 +885,11 @@ void RocketChat::onApplicationStateChanged( const Qt::ApplicationState &pState )
         } else {
             mInitialized = 1;
         }
-    } else if ( ( ( pState == Qt::ApplicationInactive ) || pState == Qt::ApplicationSuspended ) && mServerStatus ) {
+
+    }
+
+#if defined(Q_OS_ANDROID)||defined(Q_OS_IOS)
+    else if ( ( ( pState == Qt::ApplicationInactive ) || pState == Qt::ApplicationSuspended ) && mServerStatus ) {
         qDebug() << "away";
 
         if ( mNetworkConfiguration.isOnline() ) {
@@ -894,6 +900,8 @@ void RocketChat::onApplicationStateChanged( const Qt::ApplicationState &pState )
             }
         }
     }
+
+#endif
 }
 
 bool RocketChat::getDdpConnectionEstablished() const
diff --git a/rocketchatserver.cpp b/rocketchatserver.cpp
index 539f09f..a8051e3 100755
--- a/rocketchatserver.cpp
+++ b/rocketchatserver.cpp
@@ -68,7 +68,7 @@ void RocketChatServerData::initConnections()
                 }
             }
 
-            mStorage->commit();
+            mStorage->askForcommit();
 
             delete messages;
 
@@ -80,6 +80,34 @@ void RocketChatServerData::initConnections()
         protocol = QStringLiteral( "http://" );
     }
 
+    if ( mRestApi != nullptr ) {
+        mRestApi->deleteLater();
+    }
+
+    if ( mFileService != nullptr ) {
+        delete mFileService;
+    }
+
+    if ( mEmojiService != nullptr ) {
+        delete mEmojiService;
+    }
+
+    if ( mDdpApi != nullptr ) {
+        mDdpApi->deleteLater();
+    }
+
+    if ( mChannels != nullptr ) {
+        mChannels->deleteLater();
+    }
+
+    if ( mMessageService != nullptr ) {
+        mMessageService->deleteLater();
+    }
+
+    if ( mChannelService != nullptr ) {
+        mChannelService->deleteLater();
+    }
+
     setRestApi( new RestApi( this, protocol + mBaseUrl ) );
     mFileService = new FileService( this );
     mEmojiService = new EmojiService( this, mFileService, mStorage );
@@ -135,11 +163,11 @@ void RocketChatServerData::initConnections()
         if ( !tokenDb.first.isEmpty() && tokenDb.second > currentTime.toTime_t() ) {
             loginWithToken( userDb, tokenDb.first );
         } else {
-            mStorage->wipeDb();
+            wipeDbAndReconnect();
             emit loggedOut( mServerId );
         }
     } else if ( !lastServer.isEmpty() ) {
-        mStorage->wipeDb();
+        wipeDbAndReconnect();
         emit loggedOut( mServerId );
     }
 
@@ -582,6 +610,13 @@ void RocketChatServerData::offlineLogin()
     }
 }
 
+void RocketChatServerData::wipeDbAndReconnect()
+{
+    disconnectFromServer();
+    mStorage->wipeDb();
+    resume();
+}
+
 QSharedPointer<RocketChatUser> RocketChatServerData::getOwnUser() const
 {
     return mOwnUser;
@@ -605,66 +640,62 @@ QString RocketChatServerData::getBaseUrl() const
 
 void RocketChatServerData::login( const QString &pUsername, const QString &pPassword )
 {
-    if ( pUsername != mStorage->getUserName() ) {
-        mStorage->wipeDb();
-    }
+    QString pass;
 
-    QPair<QString, uint> tokenDb = mStorage->getToken();
-    QString userDb = mStorage->getUserName();
-    QDateTime currentTime = QDateTime::currentDateTime();
-
-    if ( !tokenDb.first.isEmpty() && tokenDb.second > currentTime.toTime_t() ) {
-        loginWithToken( userDb, tokenDb.first );
-    } else {
-        QString passDb = mStorage->getPassword();
-        QString pass;
-        QString username = pUsername;
-
-        if ( passDb.length() ) {
-            username = userDb;
-            pass = passDb;
-        } else {
-            QByteArray hashArray = QCryptographicHash::hash( pPassword.toUtf8(), QCryptographicHash::Sha256 );
-            pass = hashArray.toHex();
-        }
+    QByteArray hashArray = QCryptographicHash::hash( pPassword.toUtf8(), QCryptographicHash::Sha256 );
+    pass = hashArray.toHex();
 
-        loginWithHash( username, pass );
-    }
+    loginWithHash( pUsername, pass );
 }
 
 void RocketChatServerData::loginWithHash( const QString &pUsername, const QString &pPswHash )
 {
     qDebug() << "login with hash";
 
-    auto self = this;
+    RestRequestCallback meCallBackSuccess = [ = ]( QNetworkReply *, QJsonObject data, RestApi * ) {
 
+        if ( data.contains( QStringLiteral( "username" ) ) ) {
+            mUsername = data[QStringLiteral( "username" )].toString();
+            mStorage->transaction();
+            mStorage->setUserData( mUsername, "" );
+            mStorage->setToken( mResumeToken, mTokenExpire );
+            mStorage->setUserId( mUserId );
+            mStorage->askForcommit();
+            onResume();
+            onDDPAuthenticated();
+        }
+
+    };
     auto request = QSharedPointer<DDPLoginRequest>::create( pUsername, pPswHash );
 
-    DdpCallback success = [ self, pUsername, pPswHash, request ]( QJsonObject pResponse, MeteorDDP * ) {
+    DdpCallback success = [ = ]( QJsonObject pResponse, MeteorDDP * ) {
         qDebug() << "authenticated";
 
         if ( pResponse.contains( QStringLiteral( "result" ) ) ) {
             QJsonObject result = pResponse[QStringLiteral( "result" )].toObject();
 
             if ( result.contains( QStringLiteral( "token" ) ) && result.contains( QStringLiteral( "id" ) ) ) {
-                self->mConnectionState = ConnectionState::ONLINE;
-                self->mResumeToken = result[QStringLiteral( "token" )].toString();
+                mConnectionState = ConnectionState::ONLINE;
+                mResumeToken = result[QStringLiteral( "token" )].toString();
                 QJsonObject expireObject = result[QStringLiteral( "tokenExpires" )].toObject();
                 double expireDouble = expireObject[QStringLiteral( "$date" )].toDouble();
-                self->mTokenExpire = static_cast<uint>( expireDouble / 1000 );
+                mTokenExpire = static_cast<uint>( expireDouble / 1000 );
                 QString userId = result[QStringLiteral( "id" )].toString();
-                self->setUserId( userId );
-                self->mStorage->transaction();
-                self->mStorage->setUserData( pUsername, pPswHash );
-                self->mStorage->setToken( self->mResumeToken, self->mTokenExpire );
-                self->mStorage->setUserId( userId );
-                self->mRestApi->setToken( self->mResumeToken );
-                self->mRestApi->setUserId( userId );
-                self->mStorage->commit();
-                self->mDdpApi->setToken( self->mResumeToken );
-                self->mDdpApi->unsetResponseBinding( request->getFrame() );
-                self->onDDPAuthenticated();
-                emit( self->onHashLoggedIn( self->mServerId ) );
+
+                setUserId( userId );
+                mStorage->transaction();
+                mStorage->setUserData( pUsername, pPswHash );
+
+                mRestApi->setToken( mResumeToken );
+                mRestApi->setUserId( userId );
+                mStorage->askForcommit();
+                mDdpApi->setToken( mResumeToken );
+                mDdpApi->unsetResponseBinding( request->getFrame() );
+
+                RestApiRequest meRequest
+                    = RestApiRequest( new restMeRequest( meCallBackSuccess ) );
+
+                mRestApi->sendRequest( meRequest );
             }
         }
     };
@@ -842,7 +873,7 @@ void RocketChatServerData::loginWithOpenIDToken( const QString &pToken, const QS
                 self->mStorage->setUserData( self->mUsername, "" );
                 self->mStorage->setToken( self->mResumeToken, self->mTokenExpire );
                 self->mStorage->setUserId( self->mUserId );
-                self->mStorage->commit();
+                self->mStorage->askForcommit();
                 self->onResume();
                 self->onDDPAuthenticated();
             }
@@ -1687,7 +1718,7 @@ void RocketChatServerData::getCustomEmojis()
                 Q_ASSERT( result );
             }
 
-            mStorage->commit();
+            mStorage->askForcommit();
         }
 
         if ( !mCustomEmojisReady ) {
diff --git a/rocketchatserver.h b/rocketchatserver.h
index 92fa22c..e9b210d 100755
--- a/rocketchatserver.h
+++ b/rocketchatserver.h
@@ -221,7 +221,7 @@ class RocketChatServerData : public MessageListener
         void getCustomEmojis();
         RestApi *getRestApi() const;
         ChannelRepository *getChannels() const;
-        RocketChatChannelService *mChannelService;
+        RocketChatChannelService *mChannelService = nullptr;
         void handleChannelMessage( const QJsonObject &pMessage );
         uint diffToLastDDPPing();
         void sendUnsentMessages( void );
@@ -244,6 +244,8 @@ class RocketChatServerData : public MessageListener
 
         void offlineLogin();
 
+        void wipeDbAndReconnect();
+
     protected:
 
         RocketChatServerData();
@@ -278,11 +280,11 @@ class RocketChatServerData : public MessageListener
         QMap<QString, FileUploader *> mFileUploads;
         QString mCurrentChannel;
         QMutex mUnsentMutex;
-        UserModel *userModel;
-        LoginMethodsModel *loginMethodsModel;
-        ChannelModel *channelsModel;
-        ChannelModel *directModel;
-        ChannelModel *groupsModel;
+        UserModel *userModel = nullptr;
+        LoginMethodsModel *loginMethodsModel = nullptr;
+        ChannelModel *channelsModel = nullptr;
+        ChannelModel *directModel = nullptr;
+        ChannelModel *groupsModel = nullptr;
         std::function<void ( QMultiMap<QString, QSharedPointer<RocketChatMessage>> *messages )> historyLoaded;
         QString mPendingSwitchRoomRequest;
         QString mPendingSwitchRoomRequestType;
diff --git a/segfaulthandler.cpp b/segfaulthandler.cpp
index 8cd4f88..417ae93 100755
--- a/segfaulthandler.cpp
+++ b/segfaulthandler.cpp
@@ -70,7 +70,7 @@ void SegfaultHandler::segfaultHandlerMethod( int pSigno )
     PersistanceLayer *storage = PersistanceLayer::instance();
     storage->transaction();
     storage->setSetting( "ERROR", errorString );
-    storage->commit();
+    storage->askForcommit();
 #if defined(Q_OS_ANDROID) || defined(Q_OS_MACOS) || defined(Q_OS_LINUX) ||defined(Q_OS_IOS)
     qDebug() << "currThread:" << QThread::currentThreadId();
 
diff --git a/services/messageservice.cpp b/services/messageservice.cpp
index 6d808d4..f39a15e 100644
--- a/services/messageservice.cpp
+++ b/services/messageservice.cpp
@@ -103,7 +103,7 @@ void MessageService::persistMessages( const MessageList &pMessage )
         }
     };
 
-    mPersistanceLayer->commit();
+    mPersistanceLayer->askForcommit();
 }
 
 QSharedPointer<RocketChatMessage> MessageService::parseMessage( const QJsonObject &pMessageData,
diff --git a/services/rocketchatchannelservice.cpp b/services/rocketchatchannelservice.cpp
index 923bd58..159575f 100755
--- a/services/rocketchatchannelservice.cpp
+++ b/services/rocketchatchannelservice.cpp
@@ -188,7 +188,7 @@ QVector<QSharedPointer<RocketChatChannel> > RocketChatChannelService::processCha
         }
     }
 
-    mStorage->commit();
+    mStorage->askForcommit();
 
 
     return vec;
@@ -472,7 +472,7 @@ void RocketChatChannelService::deleteChannel( const QString &pId )
         mChannels->remove( pId );
         mStorage->transaction();
         mStorage->deleteChannel( pId );
-        mStorage->commit();
+        mStorage->askForcommit();
     }
 }
 
-- 
GitLab