提交 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{ ...@@ -11,6 +11,33 @@ namespace ZPDatabase{
{ {
bTerm = false; 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. * @brief Get an database connection belong to current thread.
...@@ -28,67 +55,78 @@ namespace ZPDatabase{ ...@@ -28,67 +55,78 @@ namespace ZPDatabase{
emit evt_Message(this,msg); emit evt_Message(this,msg);
return QSqlDatabase(); return QSqlDatabase();
} }
//We need a thread owner db , instead of the main DB template //We need a thread owner db , instead of the main DB template
QString threadName = QString("%1_%2").arg(strDBName).arg((quint64)currentThreadId()); QThread * pThread = currentThread();
if (false==QSqlDatabase::contains(threadName)) //We will clean the thread's db connections when thread quits.
{ if (pThread)
QSqlDatabase db = QSqlDatabase::cloneDatabase(QSqlDatabase::database(strDBName),threadName); connect (pThread,&QThread::finished,this,&DatabaseResource::on_finishedThread);
if (db.open()==false) //Make a process-unique db id
{ QString threadName = QString("%1_%2").arg(strDBName).arg((quint64)currentThread());
QString msg = "Database:"+tr(" Connection name ")+threadName+ if (false==QSqlDatabase::contains(threadName))
tr(" Can not be cloned from database %1.").arg(strDBName)+ {
tr(" Err String:") + db.lastError().text(); QSqlDatabase db = QSqlDatabase::cloneDatabase(QSqlDatabase::database(strDBName),threadName);
emit evt_Message(this,msg); if (db.open()==false)
return QSqlDatabase(); {
} QString msg = "Database:"+tr(" Connection name ")+threadName+
m_ThreadsDB[strDBName].insert(threadName); tr(" Can not be cloned from database %1.").arg(strDBName)+
} tr(" Err String:") + db.lastError().text();
//Confirm the thread-owned db is still open emit evt_Message(this,msg);
QSqlDatabase db = QSqlDatabase::database(threadName); return QSqlDatabase();
tagConnectionPara & para = m_dbNames[strDBName]; }
bool bNeedReconnect = false; m_ThreadsDB[strDBName].insert(threadName);
if (db.isOpen()==true) m_ThreadOwnedMainDBs[pThread].insert(strDBName);
{ }
if (para.testSQL.length()) //Confirm the thread-owned db is still open
{ QSqlDatabase db = QSqlDatabase::database(threadName);
QSqlQuery query(db); tagConnectionPara & para = m_dbNames[strDBName];
query.exec(para.testSQL); bool bNeedReconnect = false;
if (query.lastError().type()!=QSqlError::NoError) if (db.isOpen()==true)
{ {
QString msg = "Database:"+tr(" Connection ")+threadName+ tr(" confirm failed. MSG="); if (para.testSQL.length())
msg += query.lastError().text(); {
emit evt_Message(this,msg); QSqlQuery query(db);
bNeedReconnect = true; query.exec(para.testSQL);
} if (query.lastError().type()!=QSqlError::NoError)
} {
if (bNeedReconnect==true) QString msg = "Database:"+tr(" Connection ")+threadName+ tr(" confirm failed. MSG=");
{ msg += query.lastError().text();
db.close(); emit evt_Message(this,msg);
QSqlDatabase::removeDatabase(threadName); bNeedReconnect = true;
} }
} }
else if (bNeedReconnect==true)
bNeedReconnect = true; {
if (bNeedReconnect==true) db.close();
{ QSqlDatabase::removeDatabase(threadName);
db = QSqlDatabase::cloneDatabase(QSqlDatabase::database(strDBName),threadName); m_ThreadsDB[strDBName].remove(threadName);
if (db.open()==true) m_ThreadOwnedMainDBs[pThread].remove(strDBName);
{ }
QString msg = "Database:"+tr(" Connection ")+threadName+ tr(" Re-Established."); }
emit evt_Message(this,msg); else
} bNeedReconnect = true;
else if (bNeedReconnect==true)
{ {
QString msg = "Database:"+tr(" Connection name ")+threadName+ db = QSqlDatabase::cloneDatabase(QSqlDatabase::database(strDBName),threadName);
tr(" Can not be cloned from database %1.").arg(strDBName)+ if (db.open()==true)
tr(" Err String:") + db.lastError().text(); {
emit evt_Message(this,msg); QString msg = "Database:"+tr(" Connection ")+threadName+ tr(" Re-Established.");
m_ThreadsDB[strDBName].remove(threadName); emit evt_Message(this,msg);
return QSqlDatabase(); 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() void DatabaseResource::remove_connections()
{ {
...@@ -98,9 +136,9 @@ namespace ZPDatabase{ ...@@ -98,9 +136,9 @@ namespace ZPDatabase{
sets = currentDatabaseConnections(); sets = currentDatabaseConnections();
} }
foreach (QString name, sets.keys()) foreach (QString name, sets.keys())
{ {
this->remove_connection(name); this->remove_connection(name);
} }
} }
//!Remove Database //!Remove Database
...@@ -115,8 +153,8 @@ namespace ZPDatabase{ ...@@ -115,8 +153,8 @@ namespace ZPDatabase{
QSqlDatabase::removeDatabase(strDBName); QSqlDatabase::removeDatabase(strDBName);
QString msg = "Database:"+tr(" Connection removed ")+strDBName+ tr(" ."); QString msg = "Database:"+tr(" Connection removed ")+strDBName+ tr(" .");
emit evt_Message(this,msg); emit evt_Message(this,msg);
RemoveTreadsConnections(strDBName); RemoveTreadsConnections(strDBName);
m_ThreadsDB[strDBName].clear(); m_ThreadsDB[strDBName].clear();
} }
else else
{ {
...@@ -126,22 +164,28 @@ namespace ZPDatabase{ ...@@ -126,22 +164,28 @@ namespace ZPDatabase{
m_dbNames.remove(strDBName) ; m_dbNames.remove(strDBName) ;
} }
void DatabaseResource::RemoveTreadsConnections(QString mainName) void DatabaseResource::RemoveTreadsConnections(QString mainName)
{ {
if (m_ThreadsDB.contains(mainName)) if (m_ThreadsDB.contains(mainName))
{ {
QSet<QString> & sethreadNames = m_ThreadsDB[mainName]; QSet<QString> & sethreadNames = m_ThreadsDB[mainName];
foreach(QString str, sethreadNames) foreach(QString str, sethreadNames)
{ {
QSqlDatabase db = QSqlDatabase::database(str); QSqlDatabase db = QSqlDatabase::database(str);
if (db.isOpen()==true) if (db.isOpen()==true)
db.close(); db.close();
QSqlDatabase::removeDatabase(str); QSqlDatabase::removeDatabase(str);
QString msg = "Database:"+tr(" Connection removed ")+str+ tr(" ."); QString msg = "Database:"+tr(" Connection removed ")+str+ tr(" .");
emit evt_Message(this,msg); 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 * @brief add a database connection resource
......
...@@ -13,9 +13,6 @@ namespace ZPDatabase{ ...@@ -13,9 +13,6 @@ namespace ZPDatabase{
* @brief this class provide an database reource pool.In different thread, workers can get existing db connections * @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 * immediately without re-creation operations. The working thread does not maintain db connections, instead of
* maintaining, it just using db resources from DatabaseResource * 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 databaseresource.h "ZoomPipeline_FuncSvr/database/databaseresource.h"
*/ */
class DatabaseResource : public QThread class DatabaseResource : public QThread
...@@ -71,10 +68,12 @@ namespace ZPDatabase{ ...@@ -71,10 +68,12 @@ namespace ZPDatabase{
QMutex m_mutex_reg; QMutex m_mutex_reg;
QMap <QString,tagConnectionPara> m_dbNames; QMap <QString,tagConnectionPara> m_dbNames;
QMap <QString, QSet<QString> > m_ThreadsDB; QMap <QString, QSet<QString> > m_ThreadsDB;
QMap <QThread * , QSet<QString> > m_ThreadOwnedMainDBs;
void RemoveTreadsConnections(QString mainName); void RemoveTreadsConnections(QString mainName);
signals: signals:
void evt_Message(QObject *,QString ); void evt_Message(QObject *,QString );
public slots: public slots:
void on_finishedThread();
}; };
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册