Connect HTTP thread handlers to SessionPools. - c++

We are using the model set up in the PoCo-project library documentation. A thread/Handler is spawned for every connection to the http server. We want to connect each thread to a shared SessionPoolContainer(SPC). We are working on the assumption that we should instantiate the SPC in the HandlerFactory and give the handler a reference to the SPC.
class Handler: public Poco::Net::HTTPRequestHandler{
public:
Handler(SessionPoolContainer &spc){
//Here is where it goes wrong. "spc is private."
SessionPool sp = spc.getPool("p1");
//Todo fetch a session once we have the sessionpool reference.
}
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response){
//Do stuff.
}
};
class HandlerFactory : public Poco::Net::HTTPRequestHandlerFactory{
public:
SessionPoolContainer spc;
Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest &request){
Poco::Data::MySQL::Connector::registerConnector();
AutoPtr<SessionPool> p1 = new SessionPool("MySQL", "host=127.0.0.1;port=3306;db=testdb2;user=bachelor;password=bachelor;compress=true;auto-reconnect=true");
spc.add(p1);
if (request.getContentType().compare("Application/JSON")) {
return new Handler(spc);
}
}
};
class MyWebHTTPServerApplication : public Poco::Util::ServerApplication{
protected:
int main(const std::vector<std::string> &args){
// Instanciate HandlerFactory
Poco::Net::HTTPServer server(new HandlerFactory(), socket, pParams);
server.start();
//SIC
}
};
The error we get from this is (from the 3rd line):
/home/notandi/git/poco-1.7.2-all/cmake_install/debug/include/Poco/Data/SessionPool.h:187:9: error: 'Poco::Data::SessionPool::SessionPool(const Poco::Data::SessionPool&)' is private
SessionPool(const SessionPool&);
^ /home/notandi/QT/MySQLWithPool/main.cpp:68:41: error: within this context
SessionPool sp = spc.getPool("p");
From where I'm sitting this just needs to work and have the reference passed around.
I have tried to "friend class Handler;" in Handler with no change in status.
The relevant part of SessionPoolContainer looks like:
private:
typedef std::map<std::string, AutoPtr<SessionPool>, Poco::CILess> SessionPoolMap;
SessionPoolContainer(const SessionPoolContainer&);
SessionPoolContainer& operator = (const SessionPoolContainer&);
SessionPoolMap _sessionPools;
Poco::FastMutex _mutex;
Do I edit and recompile PoCo with SessionPoolContainer with "friend class Handler;"? How do I get around this or am I just thinking this all wrong?

From the posted code, it looks like the pool container is not needed at all because p1 pool is never added to the pool container; so, even if you could compile, spc would contain no session pools; using SessionPoolContainer makes sense only if you are connecting to multiple databases, in which case you have to add session pool to the pool container:
spc.add(p1);
However, if there is no need for SessionPoolContainer, then just pass the reference to SessionPool to the handler and get a session from it:
class Handler: public Poco::Net::HTTPRequestHandler{
public:
Handler(SessionPool &sp){
Session s = sp.get();
}
//...
};
Look at this code to get a better understanding how to use session pools and containers thereof.

Related

Qt6 Connect Signal to Lambda Function

I'm using a DataRouter class to handle communication with a QSerialPort (and then communicate the results elsewhere). The connected device sends a status package every second or so, and I would like to read it without polling the device. I tried directly using QSerialPort's waitForReadyRead function, but no matter how long I set the wait time, it always timed out. Looking here and here I saw signals can be connected to Lambda functions. Now I'm trying to connect QSerialPort's readyRead signal to a Lambda which calls my on_dataRecieved function but I get the error C2665:"QObject::connect: none of the 3 overloads could convert all of the argument types. Below is an example of what I have:
DataRouter.h
template<class SerialPort>
class DataRouter
{
public:
DataRouter ();
private slots:
on_dataRecieved();
private:
shared_ptr<SerialPort> m_port;
};
DataRouter.cpp
template<class SerialPort>
DataRouter<SerialPort>::DataRouter()
{
m_port = std::make_shared<SerialPort>()
QObject::connect(m_port, &QSerialPort::readyRead, this, [=](){this->on_dataRecieved();})
}
template<class SerialPort>
void DataRouter<SerialPort>::on_dataRecieved()
{
//Do stuff
}
If your "target" is not QObject you need to use the following overload of connect. The problem is that, you are trying to use non-QObject as "context" to determine the lifetime of the connection and that's not possible. To mitigate it you will need to release the connection somehow on DataRouter's destruction; one way is to store what connect() will have returned and call disconnect on it later on.
As for the signal coming from a smart pointer, have you tried this:
connect(m_port->get(), &QSerialPort::readyRead, &DataRouter::on_dataRecieved);
Your m_port is not entity of QSerialPort class, that's why you don't have QSerialPort::readyRead that can be emitted from it. template<class SerialPort> doesn't do what you what, it is just name of templated parameter.
You probably wanted something like this:
DataRouter.h
class DataRouter : QObject
{
public:
DataRouter ();
private slots:
on_dataRecieved();
private:
QSerialPort* m_port;
};
DataRouter.cpp
DataRouter::DataRouter()
{
m_port = new QSerialPort(this);
connect(m_port, &QSerialPort::readyRead, this, &DataRouter::on_dataRecieved);
// or connect(m_port, &QSerialPort::readyRead, this, [this](){this->on_dataRecieved();});
}
void DataRouter::on_dataRecieved()
{
//Do stuff
}
You don't have to wrap Qt classes in smart pointers as long, as you provide parent class for them. Memory freed when parent is destructed.

How can I fix and/or re-design this event class system to not require exclusively public data members?

I have an Event system in which a Manager class contains a queue of Events. The Event class is currently an abstract base class from which all specific events are derived. The idea is to allow the Manager to process() specific events that are specialized classes constructed with their own, unique parameters elsewhere in the code where the context of creation informs which event to create and how (sometimes using an Abstract Factory pattern). These Events are consumed asynchronously by Manager in a loop that continuously empties the queue, processing each event, and then destroying it as it is popped.
I designed this system to alleviate Manager from doing all of its own data manipulation. Instead, other parts of the code can queue an Event object, and that object can perform a task via its process() member, with the Manager not needing to know about it in detail.
Without an encapsulated Event system, I would be making endless additions to Manager's members: one for each task, and calling those tasks in case statements somewhere, which is terrible. I thought it would be better to use the Event system I have in the example here. This leaves Manager unchanged while various derived, specific events are defined elsewhere. This minimal example works fine, but the problem is that all derived Events need access to Manager's private data for each one's process() to have full capability as intended. If friend inheritance was allowed, simply making Event a friend class of Manager would solve the problem. Since it's not, the only way for this to work is to make all of Manager's data public (or, technically, add every new derived Event class I make as a friend to Manager).
This works, but feels wrong, and makes me think this is not the correct design. To be clear, the Manager contains a good deal of centralized information (necessary for thread sync, etc) that is more extensive than the Example would indicate. It manages network connections that will spawn a variety of different, often arbitrary events. I'd like to elegantly react to such an environment without inflating Manager with endless additional member functions every time I want to create a new type of event.
Is there a better way to achieve this code separation pattern and still retain the freedom I want for the separated code? Should I just publicize all of Manager's data after all?
The minimal Example (includes pseudocode):
class Event;
class Manager
{
public:
Manager() {}
// Event queue insertion and processing functions omitted
// private: // Commented out on purpose to allow compilation
int dataInt;
double dataReal;
std::string dataStr;
std::queue<Event *> events;
};
// Abstract Event base class with process() member
class Event
{
public:
Event(Manager * m) : manager(m)
{
process = std::bind(&Event::processKernel, this);
}
// Process the event
std::function<void(void)> process;
protected:
// Actual processing code: derived classes must define this function
virtual void processKernel() = 0;
private:
Manager * m;
};
// One example of a specialized (derived) Event
class SpecificEvent: public Event
{
public:
SpecificEvent(Manager * m, int p) : Event(m), param(p) { }
void processKernel()
{
// Intention: modify parent manager data
manager->dataInt = param;
}
private:
int param;
};
// Another specialized (derived) Event
class OtherEvent: public Event
{
public:
OtherEvent(Manager * m, double p) : Event(m), param(p) { }
void processKernel()
{
// Intention: modify parent manager data
manager->dataReal = param;
}
private:
double param;
};
// Example usage: could be inside a Manager member, or anywhere else
int main()
{
Manager manager;
// Make a SpecificEvent, pass it the manager, and its own specific parameter(s)
SpecificEvent e(&manager, 10);
//<Not shown> Add to manager's queue
// Manager processes this event at some point later with Event::process()
}
Since
If friend inheritance was allowed, simply making Event a friend class
of Manager would solve the problem
you can just get away with
struct ManagerFields { // all Manager's fields; just for the further convenience
int dataInt;
double dataReal;
};
class Manager: private ManagerFields { // only Manager and its friends know these Fields
friend class Event;
// here Manager can use dataInt, dataReal etc. just like before
};
class Event {
public:
Event(Manager* m) : manager{m} {}
virtual void process() = 0;
protected: // "friend inheritance" setup below
ManagerFields& fields() { return *manager; } // "the further convenience"
private:
Manager* manager;
};
class SpecificEvent: public Event {
public:
SpecificEvent(Manager* m, int p) : Event{m}, param{p} {}
void process() override { fields().dataInt = param; } // "friend inheritance" usage
private:
int param;
};
See the comments in the code.

QTcpSocket pointer produces SIGSEGV in a view. (QT5)

Hi,
I've got a SIGSEGV when I want to use a QTcpSocket with the following code. (more explanation at the very bottom)
Function to create a QTTCPSocket (which will keep the QTcpSocket pointer):
std::shared_ptr<QTTCPSocket> createQtSocket(std::string host, unsigned int port)
{
QTcpSocket *sock = new QTcpSocket;
sock->connectToHost(QHostAddress(QString::fromStdString(host)), port);
if (!sock->waitForConnected())
throw std::runtime_error("Connection refused");
return std::make_shared<QTTCPSocket>(sock);
}
QTTCPSocket class:
class QTTCPSocket {
public:
QTTCPSocket(QTcpSocket *socket)
: _socket(socket)
{};
~QTTCPSocket() = default;
void send(const std::string &msg)
{
std::cout << msg << std::endl;
_socket->write(&msg[0], static_cast<qint64>(msg.length())); // produces a SIGSEGV if called from a qt event (a button for example)
_socket->waitForBytesWritten(0);
}
private:
QTcpSocket *_socket;
};
Main function:
int main()
{
std::shared_ptr<QTTCPSocket> socket = createQtSocket("127.0.0.1", 33333);
ViewStateMachine vsm(socket);
vsm.init();
vsm.start();
}
ViewStateMachine class (hpp):
class ViewStateMachine {
public:
ViewStateMachine(std::shared_ptr<QTTCPSocket> sock);
void init();
void start();
std::shared_ptr<QTTCPSocket> getSock();
private:
LoginView *_loginView;
std::shared_ptr<QTTCPSocket> _sock;
};
ViewStateMachine class (cpp):
#include "ViewStateMachine.hpp"
ViewStateMachine::ViewStateMachine(std::shared_ptr<QTTCPSocket> socket)
: _sock(std::move(socket))
{
}
void ViewStateMachine::init()
{
_loginView = new LoginView(this);
_loginView->init();
}
void ViewStateMachine::start()
{
_loginView->show();
}
std::shared_ptr<QTTCPSocket> ViewStateMachine::getSock()
{
_sock->send("test1"); // SIGSEGV inside (check above)
return _sock; // if I remove _sock->send("test1"), it SIGSEGV in the shared_ptr's constructor (only if called from a qt event (a button for example)
}
LoginView is a passive class, which register an event with QObject::connect(_connectBtn, SIGNAL(clicked()), this, SLOT(onClick_connectBtn())); with onClick_connectBtn() a member function of LoginView.
All these pieces of code might be confused so here a step-by-step explanation:
Start in main(): create a QTcpSocket * contained in a QTTCPSocket class contained in a std::shared_ptr<QTTCPSocket>.
Create a ViewStateMachine instance with the shared_ptr, which will be stored in the instance. We will call it vsm.
Call vsm.init() which will create a LoginView instance with this (vsm). LoginView will store the ViewStateMachine instance.
Call vsm.start() which will call _loginView.show() (from QT's QWidget), it will show the login view.
Everything works well and we can see the login view.
However, if I want to use my socket in the LoginView :
* when I want to use it from _loginView->init() or in the LoginView's constructor, it works well!
* when I want to use it from LoginView::onClick_connectBtn (called by QT, perhaps in a special environment like a constructor, not sure), it produces a SIGSEGV where I commented above in the code (shared_ptr's constructor or write function from the QT' socket).
To get the socket from LoginView, I use ViewStateMachine::getSock() (_viewStateMachine->getSock()).
Valgrind shows
pure virtual method called
terminate called without an active exception
The shared_ptr's constructor produces a SIGSEGV when it uses its mutex to increment the value.
The write SIGSEGV when I use _socket (QT' socket). The pointer address didn't change from beginning to end.
If there's any other question, please ask!
Thanks a lot for helping :).
EDIT: It works if I replace every std::shared_ptr with a C pointer.

C++ class design with polymorphism

I am doing some networking stuff, but the question is not related to networking. I have a generic network event handler, where I can register an network connection ("NwConnection" class) and idea is whenever a message arrives on the connection, it will call me back.
class NwEventManager {
public:
using CallBack = std::function<void(std::shared_ptr<NwConnection>)>;
registerCallback(
std::shared_ptr<NwConnection> con,
CallBack rdCallback,
CallBack errorCallBack);
};
So the application will create a NwConnection and register with Event Manager.
(NwConnection is an abstract class, which internally can be a TCP/Unix domain socket etc.)
Anyway, I need to keep some per-connection information, say some statisctics.
Currently what I am doing is:
class TcpNwConnection : public NwConnection {...}
class MyNwConnection : public TcpNwConnection {
using NwConnection::NwConnection;
....
MyStatistics& getStats ()
{
return myStats_;
}
private:
MyStatistics myStats_;
};
And in the callback, which will call me back with the NwConnection Abstract class I static cast the pointer to my type and access the stats.
// read callback
[] (std::shared_ptr<NwConnection> con)
{
auto myConn = static_cast<MyNwConnection *>(con.get());
auto& stats = myConn->getStats();
}
Is this a good approach?
Obviously the problem is, if my code has to be independant of the NwConnection type, say I want to deal with TcpConnection and UnixConnection, I cannot follow this approach (unless I do with templates).
One solution is to re-write things with connection type inside the NwConnection:
class TcpStream : public AbstractStream {}
class UnixStream : public AbstractStream {}
class NwConnection {
Message read (...)
{
return stream->read(...);
}
private:
AbstractStream *stream;
};
Now I can do my static_cast and the type of connection doesnt matter.
But what is a better way to design this thing, while allowing applications to keep the per-connection data? (I am free to rewrite any part of the code.)

How can I store and forward slots using boost::signals2?

I have a problem where I'm having to instantiate instances of objects
earlier than I would like to do so because I need to connect signal
slots through some deep ownership, and I'd like to come up with a way of
storing and forwarding the slots so that I can construct objects closer
to their use site, instead of doing so as member variables.
My basic problem is that I have a process that will download an update
file on a separate thread and send a progress signal to anyone who is
interested. The signal is essentially:
typedef boost::signals2::signal<void (double)> DownloadProgress;
Assume that the implementation of the progress function mentioned
below conforms to this; the nature of the signal itself isn't very
important (although I am using functors for the most part).
The signal is set and the code is called something like this:
Updater updater;
updater.onDownloadProgress(&progress);
updater.runDownloadTask();
When you call updater.runDownloadTask(), it will start the
UpdaterDownloadTask, which starts an HTTPRequest and returns an
HTTPResponse. The HTTPResponse is the piece which interacts with the
network layer and receives the data and contains the DownloadProgress
signal. With this, my implementation looks a bit like (bottom-up from
HTTPResponse, heavily abbreviated to elide methods that aren't
particularly illustrative):
class HTTPResponse
{
public:
// this will be called for every "chunk" the underlying HTTP
// library receives
void processData(const char* data, size_t size)
{
// process the data and then send the progress signal
// assume that currentSize_ and totalSize_ are properly set
progressSignal_(currentSize_ * 100.0 / totalSize_);
}
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
progressSignal_.connect(slot);
}
private:
DownloadProgress progressSignal_;
};
class HTTPRequest
{
public:
HTTPRequest() : response_(new HTTPResponse) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
response_->connect(slot);
}
boost::shared_ptr<HTTPResponse> perform()
{
// start the request, which operates on response_.
return response_;
}
private:
boost::shared_ptr<HTTPResponse> response_;
};
class UpdaterDownloadTask : public AsyncTask
{
public:
DownloadTask() : request_(new HTTPRequest) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
request_->connect(slot);
}
void run()
{
// set up the request_ and:
request_>perform();
}
private:
boost::shared_ptr<HTTPRequest> request_;
};
class Updater
{
public:
Updater() : downloadTask_(new UpdaterDownloadTask) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
downloadTask_->onDownloadProgress(slot);
}
void runDownloadTask() { downloadTask_.submit() }
private:
boost::shared_ptr<UpdaterDownloadTask> downloadTask_;
};
So, my Updater has to have an instance of UpdaterDownloadTask that's
always around, which has an instance of HTTPRequest, which has an
instance of HTTPResponse—just because I have to forward the slot
connection from Updater (the public API entry point) to HTTPResponse
(where the signal belongs).
I would rather implement UpdaterDownloadTask::run() like so:
void run()
{
HTTPRequest request;
request.onDownloadProgress(slots_);
#if 0
// The above is more or less equivalent to
BOOST_FOREACH(const DownloadProgress::slot_type& slot, slots_)
{
request.onDownloadProgress(slot);
}
#endif
request.perform();
}
This would have similar implications at the HTTPRequest level (so I
don't have to construct the HTTPResponse until I perform the request)
and overall make for a nicer data flow with strong RAII semantics. I've
previously tried defining the slots_ variable as a vector:
std::vector<DownloadProgress::slot_type> slots_;
Yet I can only get this to work if I force the callers to call
onDownloadProgress(boost::ref(slot));.
Has anyone done this successfully, or have a good suggestion on how to
store and forward other than what I'm doing?
I think storing the slots in a vector should work ok. If you want to get rid of the need for boost::ref(...) you can remove the & from the onDownloadProgress parameter (since slot_type is copyable).
Alternatively, you could have your signal inside HTTPResponse fire and in turn fire a signal in HTTPRequest, doing that, you could connect all the slots to the signal in HTTPRequest, then once the HTTPResponse is created, you connect to the response signal onDownloadProgress(request.signalname). Where signalname is the signal your client.
pseudocode:
Request request;
request.onProgress(myProgressBarCallback);
//calls: this.signal.connect(myProgressBarCallback);
request.go();
//calls: Response response;
// and: response.onProgress(this.signal);
I hope that helps.