I have a fairly simple call I'm trying to make to a database. I have everything surrounded in try/catch and if statements, but... nothing. I know I'm making the connection (the connection refcount in MySQL increments each time I try running the script), but it never seems to return. Code is:
if (!conn.connect(db, server, username, pass))
{ /* Log error to a file */}
try
{
mysqlpp::Query query = conn.query();
query << "CALL db.test('1', '2')";
std::cout << "About to call query" << std::endl;
if (mysqlpp::StoreQueryResult res = query.store())
{
std::string toReturn = "";
res[0][0].to_string(toReturn);
std::cout << "Query called. Result: " << toReturn << std::endl;
}
}
catch(Exception e)
{ /*Output caught exception*/ }
and I get:
About to call query
as my sole output.
I have more debugging in there (query is being put together correctly, connection is correct, etc).
Anyone have any idea what might be happening, or what I should check next?
Thanks!
-- Edit: If I run the call straight from MySQL, everything works as expected, so that's not causing the problem.
You should call the query inside conn.query(); Like
std::cout << "About to call query" << std::endl;
mysqlpp::Query query = conn.query("CALL db.test('1', '2')");
if (mysqlpp::StoreQueryResult res = query.store())
{
std::string toReturn = ""; //this is not necessary
res[0][0].to_string(toReturn); //this is not necessary
for (size_t i = 0; i < res.num_rows(); ++i)
{
std::cout << "Query called. Result: " << res[i][0] << std::endl;
}
}
you can refer http://tangentsoft.net/mysql++/doc/html/userman/tutorial.html for examples
Related
I have some problem with st::async when is use this in other function other than Main function,
suppose, I have functions like flowing :
void printData()
{
for (size_t i = 0; i < 5; i++)
{
std::cout << "Test Function" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void runningAsync()
{
auto r = std::async(std::launch::async, test);
}
int main()
{
runningAsync();
std::cout << "Main Function" << std::endl;
}
the output of this code is :
Test Function
Test Function
Test Function
Test Function
Test Function
Main Function
that is not good, Main thread wait for other thread that be end.
I want runningAsync() function run in other thread and at the same time "Main Function" in main thread print on screan, this is possible with std::thread.
is that way for this running this functions an same time (concurrency)?
The reason is that std::async returns a std::future which you store in an auto variable. As soon as your future runs out of scope (at the end of runningAsync()!), its destructor blocks until the task is finished. If you do not want that, you could for example store the future in a global container.
This QUESTION answered in :
main thread waits for std::async to complete
Can I use std::async without waiting for the future limitation?
Whoever, If you store the std::future object, its lifetime will be extended to the end of main and you get the behavior you want.
void printData()
{
for (size_t i = 0; i < 5; i++)
{
std::cout << "Test Function" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
std::future<void> runningAsync()
{
return std::async(std::launch::async, test);
}
int main()
{
auto a = runningAsync();
std::cout << "Main Function" << std::endl;
}
That's a problem because std::future's destructor may block and wait for the thread to finish. see this link for more details
Consider the following two snippets of code where I am trying to launch 10000 threads:
Snippet 1
std::array<std::future<void>, 10000> furArr_;
try
{
size_t index = 0;
for (auto & fut : furArr_)
{
std::cout << "Created thread # " << index++ << std::endl;
fut = std::async(std::launch::async, fun);
}
}
catch (std::system_error & ex)
{
std::string str = ex.what();
std::cout << "Caught : " << str.c_str() << std::endl;
}
// I will call get afterwards, still 10000 threads should be active by now assuming "fun" is time consuming
Snippet 2
std::array<std::thread, 10000> threadArr;
try
{
size_t index = 0;
for (auto & thr : threadArr)
{
std::cout << "Created thread # " << index++ << std::endl;
thr = std::thread(fun);
}
}
catch (std::system_error & ex)
{
std::string str = ex.what();
std::cout << "Caught : " << str.c_str() << std::endl;
}
The first case always succeeds .i.e. I am able to create 10000 threads and then I have to wait for all of them to finish. In the second case, almost always I end up getting an exception("resource unavailable try again") after creating 1600+ threads.
With a launch policy of std::launch::async, I thought that the two snippets should behave the same way. How different std::async with a launch policy of async is from launching a thread explicitly using std::thread?
I am on Windows 10, VS2015, binary is built in x86 release mode.
Firstly, thanks to Igor Tandetnik for giving me the direction for this answer.
When we use std::async (with async launch policy), we are saying:
“I want to get this work done on a separate thread”.
When we use std::thread we are saying:
“I want to get this work done on a new thread”.
The subtle difference means that async (is usually) implemented using thread pools. Which means if we have invoked a method using async multiple times, often the thread id inside that method will repeat i.e. async allocates multiple jobs to the same set of threads from the pool. Whereas with std::thread, it never will.
This difference means that launching threads explicitly will be potentially more resource intensive (and thus the exception) than using async with async launch policy.
I have a simple sqlite function with SQLiteCpp as below on buildroot linux, it insert one row into database and will be called per second so I kept the database open. I found the memory usage keep on increasing, is it because I kept the database open? Should I close it every second? --Thanks
bool Sdb::InsertData(const Data* data)
{
std::vector<std::string> tags = data->GetTags();
try {
SQLite::Statement query(mDb, "INSERT INTO test (serial_no, generation, consumption) VALUES ('01', 0, 0);");
query.exec();
} catch (std::exception& e) {std::cout << "exception happened: " << std::endl;
return false;
}
std::cout << serial_no << " " << timestamp << " "
<< generation << " " << sqlite3_memory_used() << std::endl;
return true;
}
I am using boost 1.52.0 32 bit libraries with OpenSSL 32 bit libraries with unmanaged Visual C++ 2008 for a new client I am writing to communicate with an existing server. My test machine uses Windows 8. I am using synchronous reads and writes. The code is built into a DLL that is accessed from C#, but all asio calls are done on unmanaged threads created with boost::thread_group.
What I have discovered is that when a synchronous read is waiting for data, then a synchronous write taking place in another thread appears to be blocked and will not go out - at least with the way I have things coded. So my question is - should a synchronous write be able to be completely executed while a synchronous read is waiting for data in another thread?
I have verified that I can write data out successfully when there is no pending read in another thread. I did this by freezing the thread the read was on right before it was about to read. The thread for writing then wrote a message out. I then thawed the read thread and it was able to successfully read the response back from the server about the message that was sent.
The following method is called by the create_thread method to handle reading messages off the wire from the server:
void SSLSocket::ProcessServerRequests()
{
// This method is responsible for processing requests from a server.
Byte *pByte;
int ByteCount;
size_t BytesTransferred;
boost::system::error_code Err;
Byte* pReqBuf;
string s;
stringstream ss;
//
try
{
ss << "ProcessServerRequests: Worker thread: " << Logger::NumberToString(boost::this_thread::get_id()) << " started.\n";
Log.LogString(ss.str(), LogInfo);
// Enable the handlers for the handshaking.
IOService->run();
// Wait for the handshake to be sucessfully completed.
do
{
Sleep(50);
} while (!HandShakeReady);
//
sClientIp = pSocket->lowest_layer().remote_endpoint().address().to_string();
uiClientPort = pSocket->lowest_layer().remote_endpoint().port();
ReqAlive = true;
// If the thread that handles sending msgs to all servers has not been created yet, then create that one.
// This thread is created just once to handle all outbound msgs to all servers.
WorkerThreads.create_thread(boost::bind(&SSLSocket::SendWorkerThread));
// Loop until the user quits, or an error is detected. The read method should wait until there is something to read.
do
{
pReqBuf = BufMang.GetPtr(MsgLenBytes);
boost::asio::read(*pSocket, boost::asio::buffer(pReqBuf, MsgLenBytes), boost::asio::transfer_exactly(MsgLenBytes), Err);
if (Err)
{
s = Err.message();
if ((s.find("short r")) == string::npos)
{
ss.str("");
ss << "SSLSocket::ProcessServerRequests: read(1) error = " << Err.message() << "\n. Terminating.\n\n";
Log.LogString(ss.str(), LogError);
}
Terminate();
// Notify the client that an error has been encountered and the program needs to shut down. TBD.
}
else
{
// Get the number of bytes in the message.
pByte = pReqBuf;
B2I.B.B1 = *pByte++;
B2I.B.B2 = *pByte++;
B2I.B.B3 = *pByte++;
B2I.B.B4 = *pByte;
ByteCount = B2I.IntVal;
pReqBuf = BufMang.GetPtr(ByteCount);
// Do a synchronous read which will hang until the entire message is read off the wire.
BytesTransferred = boost::asio::read(*pSocket, boost::asio::buffer(pReqBuf, ByteCount), boost::asio::transfer_exactly(ByteCount), Err);
ss.str("");
ss << "SSLSocket::ProcessServerRequests: # bytes rcvd = " << Logger::NumberToString(BytesTransferred).c_str() << " from ";
ss << sClientIp.c_str() << " : " << Logger::NumberToString(uiClientPort) << "\n";
Log.LogString(ss.str(), LogDebug2);
Log.LogBuf(pReqBuf, (int)BytesTransferred, DisplayInHex, LogDebug3);
if ((Err) || (ByteCount != BytesTransferred))
{
if (Err)
{
ss.str("");
ss << "ProcessServerRequests:read(2) error = " << Err.message() << "\n. Terminating.\n\n";
}
else
{
ss.str("");
ss << "ProcessServerRequests:read(3) error - BytesTransferred (" << Logger::NumberToString(BytesTransferred).c_str() <<
") != ByteCount (" << Logger::NumberToString(ByteCount).c_str() << "). Terminating.\n\n";
}
Log.LogString(ss.str(), LogError);
Terminate();
// Notify the client that an error has been encountered and the program needs to shut down. TBD.
break;
}
// Call the C# callback method that will handle the message.
Log.LogString("SSLSocket::ProcessServerRequests: sending msg to the C# client.\n\n", LogDebug2);
CallbackFunction(this, BytesTransferred, (void*)pReqBuf);
}
} while (ReqAlive);
Log.LogString("SSLSocket::ProcessServerRequests: worker thread done.\n", LogInfo);
}
catch (std::exception& e)
{
stringstream ss;
ss << "SSLSocket::ProcessServerRequests: threw an error - " << e.what() << ".\n";
Log.LogString(ss.str(), LogError);
}
}
The following method is called by the create_thread method to handle sending messages to the server:
void SSLSocket::SendWorkerThread()
{
// This method handles sending msgs to the server. It is called upon 1st time class initialization.
//
DWORD WaitResult;
Log.LogString("SSLSocket::SendWorkerThread: Worker thread " + Logger::NumberToString(boost::this_thread::get_id()) + " started.\n", LogInfo);
// Loop until the user quits, or an error of some sort is thrown.
try
{
do
{
// If there are one or more msgs that need to be sent to a server, then send them out.
if (SendMsgQ.Count() > 0)
{
Message* pMsg = SendMsgQ.Pop();
// Byte* pBuf = pMsg->pBuf;
const Byte* pBuf = pMsg->pBuf;
SSLSocket* pSSL = pMsg->pSSL;
int BytesInMsg = pMsg->BytesInMsg;
boost::system::error_code Error;
unsigned int BytesTransferred = boost::asio::write(*pSSL->pSocket, boost::asio::buffer(pBuf, BytesInMsg), Error);
string s = "SSLSocket::SendWorkerThread: # bytes sent = ";
s += Logger::NumberToString(BytesInMsg).c_str();
s += "\n";
Log.LogString(s, LogDebug2);
Log.LogBuf(pBuf, BytesInMsg, DisplayInHex, LogDebug3);
if (Error)
{
Log.LogString("SSLSocket::SendWorkerThread: error sending message - " + Error.message() + "\n", LogError);
}
}
else
{
// Nothing to send, so go into a wait state.
WaitResult = WaitForSingleObject(hEvent, INFINITE);
if (WaitResult != 0L)
{
Log.LogString("SSLSocket::SendWorkerThread: WaitForSingleObject event error. Code = " + Logger::NumberToString(GetLastError()) + ". \n", LogError);
}
}
} while (ReqAlive);
Log.LogString("SSLSocket::SendWorkerThread: Worker thread " + Logger::NumberToString(boost::this_thread::get_id()) + " done.\n", LogInfo);
}
catch (std::exception& e)
{
stringstream ss;
ss << "SSLSocket::SendWorkerThread: threw an error - " << e.what() << ".\n";
Log.LogString(ss.str(), LogError);
}
}
So, if a synchronous write should be able to be executed while a synchronous read is pending in another thread, then can someone please tell me what my code is doing wrong.
Asio socket is not thread-safe, so you may not access it from different threads.
Use async_read and async_write instead.
I am very new to QT and SQLite DBMS. I am trying to open an existing database created using "sqlite3" command-line program under ubuntu Linux. The same database I am trying to access under QT using the following code :
void MainWindow::func()
{
QSqlQuery query;
accounts_db = new QSqlDatabase();
*accounts_db = QSqlDatabase::addDatabase("QSQLITE");
perror("? ");
accounts_db->setDatabaseName("/home/user/xyz.db");
QSqlError *a = new QSqlError();
*a = accounts_db->lastError();
perror(a->text().toLatin1());
if (!accounts_db->open()) {
perror("database open error :");
}
if ( !accounts_db->isOpen() ) {
perror("database is not open");
}
query.exec("select accno,branchcode,fname,lname,curbalance,accdate from accounts");
while(query.next()) {
QString str = query.value(0).toString();
std::cerr << qPrintable(str) << std::endl;
}
end:
;
}
This fails with the following errors...
No such file or directory
: Invalid argument
QSqlQuery::exec: database not open
Notice that I get "No such file or directory" after adddatabase(), have no clue whatsoever which file is it talking about. Also notice that isOpen() and open() are returning "true" (???). The "database not open" error is from db.exec() call (...I suppose...).
In desperate need of guidance...
The constructor of QSqlQuery with no parameters uses the default database for your application. Maybe it is not set yet. Use the constructor specifying the database the query is required to use:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "connection_name");
// Open db...
QSqlQuery query(db);
if (!query.exec(...)) {
// ...
}
// ...
Pay attention to how you close the connection afterwards.
EDIT: This is a test I just wrote and is working on my system. You might want to try.
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>
int main(int argc, char *argv[])
{
// Create database.
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "Connection");
db.setDatabaseName("/tmp/test.db");
if (!db.open()) {
qDebug("Error occurred opening the database.");
qDebug("%s.", qPrintable(db.lastError().text()));
return -1;
}
// Insert table.
QSqlQuery query(db);
query.prepare("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, text TEXT)");
if (!query.exec()) {
qDebug("Error occurred creating table.");
qDebug("%s.", qPrintable(db.lastError().text()));
return -1;
}
// Insert row.
query.prepare("INSERT INTO test VALUES (null, ?)");
query.addBindValue("Some text");
if (!query.exec()) {
qDebug("Error occurred inserting.");
qDebug("%s.", qPrintable(db.lastError().text()));
return -1;
}
// Query.
query.prepare("SELECT * FROM test");
if (!query.exec()) {
qDebug("Error occurred querying.");
qDebug("%s.", qPrintable(db.lastError().text()));
return -1;
}
while (query.next()) {
qDebug("id = %d, text = %s.", query.value(0).toInt(),
qPrintable(query.value(1).toString()));
}
return 0;
}
This is mostly guessing, since your code is wrong on quite a few things, including the error reporting.
The most likely problem is that your file path is simply not right, or the user you're running your application with does not have the appropriate permissions on the file and/or directory. (Note: files and directory are case sensitive in Linux.)
perror should only be used after calling a system function that actually failed and that sets errno when it does. Qt doesn't do that.
Please try running this, and update your question if you still cannot resolve your issue:
void MainWindow::func()
{
// Note: no pointer!
QSqlDatabase accounts_db = QSqlDatabase::addDatabase("QSQLITE");
accounts_db.setDatabaseName("/home/user/xyz.db");
if (!accounts_db.open())
{
qDebug() << "Could not open database file:";
qDebug() << accounts_db.lastError();
return;
}
// Note: don't construct queries before you have a database!
QSqlQuery query;
if (!query.exec("select accno,branchcode,fname,lname,curbalance,accdate from accounts"))
{
qDebug() << "Query failed:";
qDebug() << query.lastError();
return;
}
while(query.next()) {
QString str = query.value(0).toString();
std::cerr << qPrintable(str) << std::endl;
}
}
(I haven't even tried to compile this, so YMMV.)
Have a look at the SQL examples also, and look at how they handle all this there.
Alright, I created a brand new database file using sqlite3 command, now the same program in my question is working !!!.
I had also tried this before, but that time it did not work (...I hate it when that happens). I guess the previous file may be corrupted. But the previous database file could be accessed from cmdline sqlite3 program, so I was assuming that file was ok,...but apparently not.
Anyway, thanks a lot guys for giving me time, and very sorry if I wasted it :( .
I am marking this as an answer just for the sake of clarity that this question is answered. But its not exactly an answer (...because I still don't understand what was happening !? )
Thanks again...
EDIT :
Here is the code
QSqlError *a = new QSqlError();
accounts_db = new QSqlDatabase();
*accounts_db = QSqlDatabase::addDatabase("QSQLITE");
accounts_db->setDatabaseName("/home/user/test.db");
if ( !accounts_db->open() ) {
qDebug() << accounts_db->lastError();
qDebug() << "Could not open database file:";
}
QSqlQuery query;
if ( !(accounts_db->isOpen()) ) {
qDebug() << accounts_db->lastError();
qDebug() << ": Could not open database file:";
goto end; // quit if not successful
}
query.exec("select * from accounts");
while(query.next()) {
// loop for i columns
QString str = query.value(i).toString();
std::cerr << qPrintable(str) << std::endl ;
// loop
}
end:
;