Hi all,

My problem is as follows: I have an SSL server where multiple clients can connect to. For each client I open a separate thread.

For each request to the database I need to prepare the database as shown in function "authenticateUser" and close the connection once I am finished in order not to overload the database.


The code of the thread is as follows:

Qt Code:
  1. SslThread::SslThread(int handle, int timeout, QObject *parent) :
  2. QThread(parent)
  3. {
  4. m_sockHandle = handle;
  5. m_connName = QVariant(handle).toString();
  6. m_connTimeOut = timeout;
  7. }
  8.  
  9. SslThread::~SslThread()
  10. {
  11. qDebug("Thread Destructor");
  12. qDebug()<<"socket = "<< m_connName;
  13. QSqlDatabase::removeDatabase(m_connName);
  14. }
  15.  
  16. void SslThread::run()
  17. {
  18. QSslSocket socket;
  19. m_rxTx = new RxTx(&socket);
  20.  
  21. if (!socket.setSocketDescriptor(m_sockHandle))
  22. {
  23. qDebug()<<tr("Descriptor failed with %1").arg(socket.errorString());
  24. return;
  25. }
  26. socket.setPrivateKey(":/Certificates/mycert_key.pem");
  27. socket.setLocalCertificate(":/Certificates/mycert.pem");
  28.  
  29. QFile f(":/Certificates/cacert.pem");
  30. f.open(QIODevice::ReadOnly);
  31. QSslCertificate cert(f.readAll());
  32. if (!cert.isValid())
  33. qDebug("Invalid Certificate");
  34. else
  35. socket.addCaCertificate(cert);
  36.  
  37. connect(&socket, SIGNAL(disconnected()), this, SLOT(killThread()));
  38. connect(m_rxTx, SIGNAL(packetReceived(QByteArray)), this, SLOT(handleIncomingMessage(QByteArray)));
  39.  
  40. QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", m_connName);
  41. if (!db.isValid())
  42. {
  43. qCritical() << tr("Could not open the database QMYSQL:%1").arg(m_connName);
  44. return;
  45. }
  46.  
  47. db.setDatabaseName("testDB");
  48. db.setHostName("localhost");
  49. db.setPort(3306);
  50.  
  51. if (!db.open("dbUser", "dbPass"))
  52. {
  53. qDebug()<<"OpenDB Error:" << db.lastError().text();
  54. return;
  55. }
  56. db.close();
  57. socket.startServerEncryption();
  58. //errTimer.setInterval(m_connTimeOut);
  59. //connect(&errTimer, SIGNAL(timeout()), this, SLOT(killThread()));
  60. //errTimer.start();
  61. exec();
  62. qDebug("Just after exec...");
  63. }
  64.  
  65. void SslThread::killThread()
  66. {
  67. quit();
  68. }
  69.  
  70. void SslThread::handleIncomingMessage(QByteArray ba)
  71. {
  72. QDataStream ds(&ba, QIODevice::ReadOnly);
  73. quint32 command;
  74. ds >> command;
  75. switch (command)
  76. {
  77. case PROT_LOGIN:
  78. {
  79. QString user;
  80. QString pass;
  81. ds >> user;
  82. ds >> pass;
  83. authenticateUser(user, pass);
  84. }
  85. break;
  86. default:
  87. qWarning() << tr("Unknown command %1 from client").arg(command);
  88. break;
  89. }
  90. }
  91.  
  92. void SslThread::authenticateUser(QString userName, QString password)
  93. {
  94. QSqlDatabase db = QSqlDatabase::database(m_connName, false);
  95. db.setDatabaseName("testDB");
  96. db.setHostName("localhost");
  97. db.setPort(3306);
  98. if (!db.isValid())
  99. {
  100. qWarning() << tr("The database is not vaild");
  101. return;
  102. }
  103. if (!db.open("dbUser", "dbPass"))
  104. {
  105. qWarning() << tr("Could not open the database");
  106. return;
  107. }
  108. QSqlQuery query(db);
  109. query.exec("Do something...");
  110. ....
  111. db.close();
  112. }
To copy to clipboard, switch view to plain text mode 

My first question: If I have many functions like "authenticateUser" which need to access the database, how do I prepare a single instance of the database connection and set up a query and use it immediately instead of setting database parameters each time?

My second question: If I commit the following section in the "run" function:
Qt Code:
  1. #if 0
  2. if (!db.open("dbUser", "dbPass"))
  3. {
  4. qDebug()<<"OpenDB Error:" << db.lastError().text();
  5. return;
  6. }
  7. #endif
To copy to clipboard, switch view to plain text mode 
and the connection is dropped (by client or by closing the sever), I get the following error:
"Error in my_thread_global_end(): 1 threads didn't exit"
It's like I need to open the connection for the first time in order to use it later by "QSqlDatabase::database(m_connName, false)" function.


I really need help on this one.

Thanks in advance.