提交 7c5ee8d8 编写于 作者: 丁劲犇's avatar 丁劲犇 😸

Add a thread-quitting cleaning method. when a thread is quitting, its finished...

Add a thread-quitting cleaning method. when a thread is quitting, its finished signal will be caugth,
so that , db resource class can clean the database connections belongs to this thread one by one.
this method is very important in some situation, such as Qt-concurrent threading, threads will be created, deleted frequently.
上级 eaac6f97
......@@ -11,6 +11,33 @@ namespace ZPDatabase{
{
bTerm = false;
}
//When a QThread finished, the database for this thread should be removed.
void DatabaseResource::on_finishedThread()
{
QMutexLocker locker(&m_mutex_reg);
QThread * pThread = qobject_cast<QThread *>( sender());
//Get The quiting thread
if (pThread && m_ThreadOwnedMainDBs.contains(pThread) )
{
QSet<QString> mainNames = m_ThreadOwnedMainDBs[pThread];
//Remove every thread-owned db names for this thread.
foreach (QString mainName, mainNames)
{
QString threadName = QString("%1_%2").arg(mainName).arg((quint64)pThread);
QSqlDatabase db = QSqlDatabase::database(threadName);
if (db.isOpen()==true)
db.close();
QSqlDatabase::removeDatabase(threadName);
QString msg = "Database:"+tr(" Connection removed ")+threadName+ tr(" .");
emit evt_Message(this,msg);
//Remove the key map
m_ThreadsDB[mainName].remove(threadName);
}
//Completly remove this thread's ThreadOwnedMainDBs
m_ThreadOwnedMainDBs.remove(pThread);
}
}
/**
* @brief Get an database connection belong to current thread.
......@@ -28,67 +55,78 @@ namespace ZPDatabase{
emit evt_Message(this,msg);
return QSqlDatabase();
}
//We need a thread owner db , instead of the main DB template
QString threadName = QString("%1_%2").arg(strDBName).arg((quint64)currentThreadId());
if (false==QSqlDatabase::contains(threadName))
{
QSqlDatabase db = QSqlDatabase::cloneDatabase(QSqlDatabase::database(strDBName),threadName);
if (db.open()==false)
{
QString msg = "Database:"+tr(" Connection name ")+threadName+
tr(" Can not be cloned from database %1.").arg(strDBName)+
tr(" Err String:") + db.lastError().text();
emit evt_Message(this,msg);
return QSqlDatabase();
}
m_ThreadsDB[strDBName].insert(threadName);
}
//Confirm the thread-owned db is still open
QSqlDatabase db = QSqlDatabase::database(threadName);
tagConnectionPara & para = m_dbNames[strDBName];
bool bNeedReconnect = false;
if (db.isOpen()==true)
{
if (para.testSQL.length())
{
QSqlQuery query(db);
query.exec(para.testSQL);
if (query.lastError().type()!=QSqlError::NoError)
{
QString msg = "Database:"+tr(" Connection ")+threadName+ tr(" confirm failed. MSG=");
msg += query.lastError().text();
emit evt_Message(this,msg);
bNeedReconnect = true;
}
}
if (bNeedReconnect==true)
{
db.close();
QSqlDatabase::removeDatabase(threadName);
}
}
else
bNeedReconnect = true;
if (bNeedReconnect==true)
{
db = QSqlDatabase::cloneDatabase(QSqlDatabase::database(strDBName),threadName);
if (db.open()==true)
{
QString msg = "Database:"+tr(" Connection ")+threadName+ tr(" Re-Established.");
emit evt_Message(this,msg);
}
else
{
QString msg = "Database:"+tr(" Connection name ")+threadName+
tr(" Can not be cloned from database %1.").arg(strDBName)+
tr(" Err String:") + db.lastError().text();
emit evt_Message(this,msg);
m_ThreadsDB[strDBName].remove(threadName);
return QSqlDatabase();
//We need a thread owner db , instead of the main DB template
QThread * pThread = currentThread();
//We will clean the thread's db connections when thread quits.
if (pThread)
connect (pThread,&QThread::finished,this,&DatabaseResource::on_finishedThread);
//Make a process-unique db id
QString threadName = QString("%1_%2").arg(strDBName).arg((quint64)currentThread());
if (false==QSqlDatabase::contains(threadName))
{
QSqlDatabase db = QSqlDatabase::cloneDatabase(QSqlDatabase::database(strDBName),threadName);
if (db.open()==false)
{
QString msg = "Database:"+tr(" Connection name ")+threadName+
tr(" Can not be cloned from database %1.").arg(strDBName)+
tr(" Err String:") + db.lastError().text();
emit evt_Message(this,msg);
return QSqlDatabase();
}
m_ThreadsDB[strDBName].insert(threadName);
m_ThreadOwnedMainDBs[pThread].insert(strDBName);
}
//Confirm the thread-owned db is still open
QSqlDatabase db = QSqlDatabase::database(threadName);
tagConnectionPara & para = m_dbNames[strDBName];
bool bNeedReconnect = false;
if (db.isOpen()==true)
{
if (para.testSQL.length())
{
QSqlQuery query(db);
query.exec(para.testSQL);
if (query.lastError().type()!=QSqlError::NoError)
{
QString msg = "Database:"+tr(" Connection ")+threadName+ tr(" confirm failed. MSG=");
msg += query.lastError().text();
emit evt_Message(this,msg);
bNeedReconnect = true;
}
}
if (bNeedReconnect==true)
{
db.close();
QSqlDatabase::removeDatabase(threadName);
m_ThreadsDB[strDBName].remove(threadName);
m_ThreadOwnedMainDBs[pThread].remove(strDBName);
}
}
else
bNeedReconnect = true;
if (bNeedReconnect==true)
{
db = QSqlDatabase::cloneDatabase(QSqlDatabase::database(strDBName),threadName);
if (db.open()==true)
{
QString msg = "Database:"+tr(" Connection ")+threadName+ tr(" Re-Established.");
emit evt_Message(this,msg);
m_ThreadsDB[strDBName].insert(threadName);
m_ThreadOwnedMainDBs[pThread].insert(strDBName);
}
else
{
QString msg = "Database:"+tr(" Connection name ")+threadName+
tr(" Can not be cloned from database %1.").arg(strDBName)+
tr(" Err String:") + db.lastError().text();
emit evt_Message(this,msg);
m_ThreadsDB[strDBName].remove(threadName);
m_ThreadOwnedMainDBs[pThread].remove(strDBName);
return QSqlDatabase();
}
}
return db;
}
}
return db;
}
void DatabaseResource::remove_connections()
{
......@@ -98,9 +136,9 @@ namespace ZPDatabase{
sets = currentDatabaseConnections();
}
foreach (QString name, sets.keys())
{
this->remove_connection(name);
}
{
this->remove_connection(name);
}
}
//!Remove Database
......@@ -115,8 +153,8 @@ namespace ZPDatabase{
QSqlDatabase::removeDatabase(strDBName);
QString msg = "Database:"+tr(" Connection removed ")+strDBName+ tr(" .");
emit evt_Message(this,msg);
RemoveTreadsConnections(strDBName);
m_ThreadsDB[strDBName].clear();
RemoveTreadsConnections(strDBName);
m_ThreadsDB[strDBName].clear();
}
else
{
......@@ -126,22 +164,28 @@ namespace ZPDatabase{
m_dbNames.remove(strDBName) ;
}
void DatabaseResource::RemoveTreadsConnections(QString mainName)
{
if (m_ThreadsDB.contains(mainName))
{
QSet<QString> & sethreadNames = m_ThreadsDB[mainName];
foreach(QString str, sethreadNames)
{
QSqlDatabase db = QSqlDatabase::database(str);
if (db.isOpen()==true)
db.close();
QSqlDatabase::removeDatabase(str);
QString msg = "Database:"+tr(" Connection removed ")+str+ tr(" .");
emit evt_Message(this,msg);
}
}
}
void DatabaseResource::RemoveTreadsConnections(QString mainName)
{
if (m_ThreadsDB.contains(mainName))
{
QSet<QString> & sethreadNames = m_ThreadsDB[mainName];
foreach(QString str, sethreadNames)
{
QSqlDatabase db = QSqlDatabase::database(str);
if (db.isOpen()==true)
db.close();
QSqlDatabase::removeDatabase(str);
QString msg = "Database:"+tr(" Connection removed ")+str+ tr(" .");
emit evt_Message(this,msg);
}
//Remove thread map.
foreach (QThread * ptr, m_ThreadOwnedMainDBs.keys())
{
QSet<QString> & threadOwnedMainDB = m_ThreadOwnedMainDBs[ptr];
threadOwnedMainDB.remove(mainName);
}
}
}
/**
* @brief add a database connection resource
......
......@@ -13,9 +13,6 @@ namespace ZPDatabase{
* @brief this class provide an database reource pool.In different thread, workers can get existing db connections
* immediately without re-creation operations. The working thread does not maintain db connections, instead of
* maintaining, it just using db resources from DatabaseResource
* Important!! When Ever a thread calls DatabaseResource::databse(), a thread-owned dbconnection
* will be cloned from main db connection. be careful, this class does not auto remove connections
* unless main connection has been removed by DatabaseResource::remove_connection(s)
* @class DatabaseResource databaseresource.h "ZoomPipeline_FuncSvr/database/databaseresource.h"
*/
class DatabaseResource : public QThread
......@@ -71,10 +68,12 @@ namespace ZPDatabase{
QMutex m_mutex_reg;
QMap <QString,tagConnectionPara> m_dbNames;
QMap <QString, QSet<QString> > m_ThreadsDB;
QMap <QThread * , QSet<QString> > m_ThreadOwnedMainDBs;
void RemoveTreadsConnections(QString mainName);
signals:
void evt_Message(QObject *,QString );
public slots:
void on_finishedThread();
};
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册