Thread: [Cppcms-users] Design decision
Brought to you by:
artyom-beilis
From: Christian G. <chr...@gm...> - 2012-10-04 09:02:26
|
Hi all. My cppcms based web application is in a quite good shape and I got some ideas what new features could be added. + Detection of networking changes via PF_NETLINK socket At the moment it is possible to configure networking settings via cppcms. For instance, it is possible to use manual mode for an ethernet interface to specify ip. netmask etc. or use DHCP mode. If DHCP gets used the running system starts dhcp client and it could takes some seconds until it got a valid IP address. The basic idea is now to use SSE (server send events) and some detection threads. Create a (cppcms ?) thread per ethernet interface and run something like http://stackoverflow.com/questions/579783/how-to-detect-ip-address-change-programmatically-in-linux Then I would have a singleton class for SSE where I can call e.g. SSE::instance()->ethernet("eth0", ip,...) and my front-end can update the values. Can this work? --- Christian Gmeiner, MSc |
From: Artyom B. <art...@ya...> - 2012-10-04 09:20:42
|
>________________________________ > From: Christian Gmeiner <chr...@gm...> >To: cpp...@li... >Sent: Thursday, October 4, 2012 11:01 AM >Subject: [Cppcms-users] Design decision > >Hi all. > >My cppcms based web application is in a quite good shape and I got >some ideas what >new features could be added. > >+ Detection of networking changes via PF_NETLINK socket > >At the moment it is possible to configure networking settings via >cppcms. For instance, >it is possible to use manual mode for an ethernet interface to specify >ip. netmask etc. or >use DHCP mode. If DHCP gets used the running system starts dhcp client >and it could >takes some seconds until it got a valid IP address. > >The basic idea is now to use SSE (server send events) and some >detection threads. > >Create a (cppcms ?) thread per ethernet interface and run something like >http://stackoverflow.com/questions/579783/how-to-detect-ip-address-change-programmatically-in-linux > >Then I would have a singleton class for SSE where I can call e.g. >SSE::instance()->ethernet("eth0", ip,...) and my front-end can update >the values. > >Can this work? > > >--- >Christian Gmeiner, MSc > Why not? Several points 1. In there link there is an example to use it without polling, so just use basic_io_device to check for readability and then call recv So basically you don't need threads just implement event driven handling in the event loop (see tutorial for examples) 2. 2nd point is that if you still want to use threads, make sure that you do not use can SSE asynchronous app from another thread, i.e. you need to post a callback to the event loop (via post) that would be executed in the main event loop. Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ |
From: Christian G. <chr...@gm...> - 2012-10-04 12:11:32
|
2012/10/4 Artyom Beilis <art...@ya...>: >>________________________________ > >> From: Christian Gmeiner <chr...@gm...> >>To: cpp...@li... >>Sent: Thursday, October 4, 2012 11:01 AM >>Subject: [Cppcms-users] Design decision >> >>Hi all. >> >>My cppcms based web application is in a quite good shape and I got >>some ideas what >>new features could be added. >> >>+ Detection of networking changes via PF_NETLINK socket >> >>At the moment it is possible to configure networking settings via >>cppcms. For instance, >>it is possible to use manual mode for an ethernet interface to specify >>ip. netmask etc. or >>use DHCP mode. If DHCP gets used the running system starts dhcp client >>and it could >>takes some seconds until it got a valid IP address. >> >>The basic idea is now to use SSE (server send events) and some >>detection threads. >> >>Create a (cppcms ?) thread per ethernet interface and run something like >>http://stackoverflow.com/questions/579783/how-to-detect-ip-address-change-programmatically-in-linux >> >>Then I would have a singleton class for SSE where I can call e.g. >>SSE::instance()->ethernet("eth0", ip,...) and my front-end can update >>the values. >> >>Can this work? >> >> >>--- >>Christian Gmeiner, MSc >> > > Why not? > > Several points > > 1. In there link there is an example to use it without polling, so just use basic_io_device to check > for readability and then call recv > > So basically you don't need threads just implement event driven > handling in the event loop (see tutorial for examples) > This looks like the elegant solution I am looking for :) But... I don't get it up and running :/ I decided to go this way: #ifndef NETLINK_H_ #define NETLINK_H_ #include <booster/aio/basic_io_device.h> class Netlink : public booster::aio::basic_io_device { public: Netlink(); ~Netlink(); void read(booster::system::error_code const &e); private: char _buffer[4096]; }; #endif /* NETLINK_H_ */ And this is my main() // start cppcms service try { cppcms::service srv(argc, argv); booster::aio::io_service &io_srv = srv.get_io_service(); Netlink netlink; netlink.set_io_service(io_srv); netlink.on_readable(std::bind(&Netlink::read)); srv.applications_pool().mount(cppcms::applications_factory<Tssw>()); srv.run(); } catch (std::exception const &e) { std::cerr << e.what() << std::endl; } The big big problem is how should I use on_readable(..) ? The above example does not compile. ---- Christian Gmeiner, MSc |
From: Artyom B. <art...@ya...> - 2012-10-04 12:37:13
|
Read more about std::bind / boost::bind netlink.on_readable(std::bind(&Netlink::read)); should be netlink.on_readable(std::bind(&Netlink::read,&netlink,std::placeholders::_1)); But if you already use C++11... netlink.on_readable( [&](booster::system::error_code const &e) { netlink.read(e); }); Much easier to understand. Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ >________________________________ > From: Christian Gmeiner <chr...@gm...> >To: Artyom Beilis <art...@ya...>; cpp...@li... >Sent: Thursday, October 4, 2012 2:11 PM >Subject: Re: [Cppcms-users] Design decision > >2012/10/4 Artyom Beilis <art...@ya...>: >>>________________________________ >> >>> From: Christian Gmeiner <chr...@gm...> >>>To: cpp...@li... >>>Sent: Thursday, October 4, 2012 11:01 AM >>>Subject: [Cppcms-users] Design decision >>> >>>Hi all. >>> >>>My cppcms based web application is in a quite good shape and I got >>>some ideas what >>>new features could be added. >>> >>>+ Detection of networking changes via PF_NETLINK socket >>> >>>At the moment it is possible to configure networking settings via >>>cppcms. For instance, >>>it is possible to use manual mode for an ethernet interface to specify >>>ip. netmask etc. or >>>use DHCP mode. If DHCP gets used the running system starts dhcp client >>>and it could >>>takes some seconds until it got a valid IP address. >>> >>>The basic idea is now to use SSE (server send events) and some >>>detection threads. >>> >>>Create a (cppcms ?) thread per ethernet interface and run something like >>>http://stackoverflow.com/questions/579783/how-to-detect-ip-address-change-programmatically-in-linux >>> >>>Then I would have a singleton class for SSE where I can call e.g. >>>SSE::instance()->ethernet("eth0", ip,...) and my front-end can update >>>the values. >>> >>>Can this work? >>> >>> >>>--- >>>Christian Gmeiner, MSc >>> >> >> Why not? >> >> Several points >> >> 1. In there link there is an example to use it without polling, so just use basic_io_device to check >> for readability and then call recv >> >> So basically you don't need threads just implement event driven >> handling in the event loop (see tutorial for examples) >> > >This looks like the elegant solution I am looking for :) > >But... I don't get it up and running :/ > >I decided to go this way: > >#ifndef NETLINK_H_ >#define NETLINK_H_ > >#include <booster/aio/basic_io_device.h> > >class Netlink : public booster::aio::basic_io_device >{ >public: > Netlink(); > ~Netlink(); > > void read(booster::system::error_code const &e); > >private: > char _buffer[4096]; >}; > >#endif /* NETLINK_H_ */ > > >And this is my main() > > // start cppcms service > try > { > cppcms::service srv(argc, argv); > > booster::aio::io_service &io_srv = srv.get_io_service(); > > Netlink netlink; > netlink.set_io_service(io_srv); > netlink.on_readable(std::bind(&Netlink::read)); > > srv.applications_pool().mount(cppcms::applications_factory<Tssw>()); > srv.run(); > } > catch (std::exception const &e) > { > std::cerr << e.what() << std::endl; > } > > >The big big problem is how should I use on_readable(..) ? The above example does >not compile. > >---- >Christian Gmeiner, MSc > >------------------------------------------------------------------------------ >Don't let slow site performance ruin your business. Deploy New Relic APM >Deploy New Relic app performance management and know exactly >what is happening inside your Ruby, Python, PHP, Java, and .NET app >Try New Relic at no cost today and get our sweet Data Nerd shirt too! >http://p.sf.net/sfu/newrelic-dev2dev >_______________________________________________ >Cppcms-users mailing list >Cpp...@li... >https://lists.sourceforge.net/lists/listinfo/cppcms-users > > > |
From: Christian G. <chr...@gm...> - 2012-10-04 12:46:46
|
2012/10/4 Artyom Beilis <art...@ya...>: > Read more about std::bind / boost::bind > > netlink.on_readable(std::bind(&Netlink::read)); > > should be > > > netlink.on_readable(std::bind(&Netlink::read,&netlink,std::placeholders::_1)); > > But if you already use C++11... I am using it to get std::bind (gcc version 4.6.3) as I don't wand an other dependency only to get bind working. > > netlink.on_readable( [&](booster::system::error_code const &e) { > netlink.read(e); > }); > > Much easier to understand. > I really should have a closer look at C++11... thanks --- Christian Gmeiner MSc > Artyom Beilis > -------------- > CppCMS - C++ Web Framework: http://cppcms.com/ > CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ > > ________________________________ > From: Christian Gmeiner <chr...@gm...> > To: Artyom Beilis <art...@ya...>; cpp...@li... > Sent: Thursday, October 4, 2012 2:11 PM > Subject: Re: [Cppcms-users] Design decision > > 2012/10/4 Artyom Beilis <art...@ya...>: >>>________________________________ >> >>> From: Christian Gmeiner <chr...@gm...> >>>To: cpp...@li... >>>Sent: Thursday, October 4, 2012 11:01 AM >>>Subject: [Cppcms-users] Design decision >>> >>>Hi all. >>> >>>My cppcms based web application is in a quite good shape and I got >>>some ideas what >>>new features could be added. >>> >>>+ Detection of networking changes via PF_NETLINK socket >>> >>>At the moment it is possible to configure networking settings via >>>cppcms. For instance, >>>it is possible to use manual mode for an ethernet interface to specify >>>ip. netmask etc. or >>>use DHCP mode. If DHCP gets used the running system starts dhcp client >>>and it could >>>takes some seconds until it got a valid IP address. >>> >>>The basic idea is now to use SSE (server send events) and some >>>detection threads. >>> >>>Create a (cppcms ?) thread per ethernet interface and run something like >>>http://stackoverflow.com/questions/579783/how-to-detect-ip-address-change-programmatically-in-linux >>> >>>Then I would have a singleton class for SSE where I can call e.g. >>>SSE::instance()->ethernet("eth0", ip,...) and my front-end can update >>>the values. >>> >>>Can this work? >>> >>> >>>--- >>>Christian Gmeiner, MSc >>> >> >> Why not? >> >> Several points >> >> 1. In there link there is an example to use it without polling, so just >> use basic_io_device to check >> for readability and then call recv >> >> So basically you don't need threads just implement event driven >> handling in the event loop (see tutorial for examples) >> > > This looks like the elegant solution I am looking for :) > > But... I don't get it up and running :/ > > I decided to go this way: > > #ifndef NETLINK_H_ > #define NETLINK_H_ > > #include <booster/aio/basic_io_device.h> > > class Netlink : public booster::aio::basic_io_device > { > public: > Netlink(); > ~Netlink(); > > void read(booster::system::error_code const &e); > > private: > char _buffer[4096]; > }; > > #endif /* NETLINK_H_ */ > > > And this is my main() > > // start cppcms service > try > { > cppcms::service srv(argc, argv); > > booster::aio::io_service &io_srv = srv.get_io_service(); > > Netlink netlink; > netlink.set_io_service(io_srv); > netlink.on_readable(std::bind(&Netlink::read)); > > srv.applications_pool().mount(cppcms::applications_factory<Tssw>()); > srv.run(); > } > catch (std::exception const &e) > { > std::cerr << e.what() << std::endl; > } > > > The big big problem is how should I use on_readable(..) ? The above example > does > not compile. > > ---- > Christian Gmeiner, MSc > > ------------------------------------------------------------------------------ > Don't let slow site performance ruin your business. Deploy New Relic APM > Deploy New Relic app performance management and know exactly > what is happening inside your Ruby, Python, PHP, Java, and .NET app > Try New Relic at no cost today and get our sweet Data Nerd shirt too! > http://p.sf.net/sfu/newrelic-dev2dev > _______________________________________________ > Cppcms-users mailing list > Cpp...@li... > https://lists.sourceforge.net/lists/listinfo/cppcms-users > > > > ------------------------------------------------------------------------------ > Don't let slow site performance ruin your business. Deploy New Relic APM > Deploy New Relic app performance management and know exactly > what is happening inside your Ruby, Python, PHP, Java, and .NET app > Try New Relic at no cost today and get our sweet Data Nerd shirt too! > http://p.sf.net/sfu/newrelic-dev2dev > _______________________________________________ > Cppcms-users mailing list > Cpp...@li... > https://lists.sourceforge.net/lists/listinfo/cppcms-users > |
From: Christian G. <chr...@gm...> - 2012-10-04 14:41:05
|
2012/10/4 Christian Gmeiner <chr...@gm...>: > 2012/10/4 Artyom Beilis <art...@ya...>: >> Read more about std::bind / boost::bind >> >> netlink.on_readable(std::bind(&Netlink::read)); >> >> should be >> >> >> netlink.on_readable(std::bind(&Netlink::read,&netlink,std::placeholders::_1)); >> >> But if you already use C++11... > > I am using it to get std::bind (gcc version 4.6.3) as I don't wand an > other dependency > only to get bind working. > >> >> netlink.on_readable( [&](booster::system::error_code const &e) { >> netlink.read(e); >> }); >> >> Much easier to understand. >> > > I really should have a closer look at C++11... > The netlink stuff works and I get some messages on stderr that I got a new IP. As far as I understood the event system of cppcms I should make use of post(..) now. This is my current main // start cppcms service try { cppcms::service srv(argc, argv); // add server send events asynchronous application booster::intrusive_ptr<SSE> sse = new SSE(srv); srv.applications_pool().mount(sse); // add netlink listner booster::aio::io_service &io_srv = srv.get_io_service(); Netlink netlink; netlink.set_io_service(io_srv); //netlink.on_readable(std::bind(&Netlink::read, &netlink)); netlink.on_readable( [&](booster::system::error_code const &e) { netlink.read(e); }); srv.applications_pool().mount(cppcms::applications_factory<Tssw>()); srv.run(); } catch (std::exception const &e) { std::cerr << e.what() << std::endl; } In the SSE class I have a quite simple method called handle: void SSE::handle(std::string name, std::string ip) { std::ostringstream ss; ss << name << ", " << ip; _stream->update(ss.str()); } Now in my Netlink class I need to post an handler that SSE:handle gets called... but how? void Netlink::read(booster::system::error_code const &e) { int len; struct nlmsghdr *nlh; nlh = (struct nlmsghdr *)_buffer; while ((len = recv(this->native(), nlh, 4096, 0)) > 0) { while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) { if (nlh->nlmsg_type == RTM_NEWADDR) { struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh); struct rtattr *rth = IFA_RTA(ifa); int rtl = IFA_PAYLOAD(nlh); while (rtl && RTA_OK(rth, rtl)) { if (rth->rta_type == IFA_LOCAL) { uint32_t ipaddr = htonl(*((uint32_t *) RTA_DATA(rth))); char name[IFNAMSIZ]; if_indextoname(ifa->ifa_index, name); fprintf(stderr, "%s is now %d.%d.%d.%d\n", name, (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff, (ipaddr >> 8) & 0xff, ipaddr & 0xff); // inform our SSE application by posting a new event // into the event loop this->get_io_service().post(std::bind(&SSE::handle, ...)); <<-- ?!?! } rth = RTA_NEXT(rth, rtl); } } nlh = NLMSG_NEXT(nlh, len); } } } I have looked quite deeply into post(..) usages, but I don't get it :/ I have seen binder's - what is the concept behind them? thanks --- Christian Gmeiner MSc > thanks > --- > Christian Gmeiner MSc > >> Artyom Beilis >> -------------- >> CppCMS - C++ Web Framework: http://cppcms.com/ >> CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ >> >> ________________________________ >> From: Christian Gmeiner <chr...@gm...> >> To: Artyom Beilis <art...@ya...>; cpp...@li... >> Sent: Thursday, October 4, 2012 2:11 PM >> Subject: Re: [Cppcms-users] Design decision >> >> 2012/10/4 Artyom Beilis <art...@ya...>: >>>>________________________________ >>> >>>> From: Christian Gmeiner <chr...@gm...> >>>>To: cpp...@li... >>>>Sent: Thursday, October 4, 2012 11:01 AM >>>>Subject: [Cppcms-users] Design decision >>>> >>>>Hi all. >>>> >>>>My cppcms based web application is in a quite good shape and I got >>>>some ideas what >>>>new features could be added. >>>> >>>>+ Detection of networking changes via PF_NETLINK socket >>>> >>>>At the moment it is possible to configure networking settings via >>>>cppcms. For instance, >>>>it is possible to use manual mode for an ethernet interface to specify >>>>ip. netmask etc. or >>>>use DHCP mode. If DHCP gets used the running system starts dhcp client >>>>and it could >>>>takes some seconds until it got a valid IP address. >>>> >>>>The basic idea is now to use SSE (server send events) and some >>>>detection threads. >>>> >>>>Create a (cppcms ?) thread per ethernet interface and run something like >>>>http://stackoverflow.com/questions/579783/how-to-detect-ip-address-change-programmatically-in-linux >>>> >>>>Then I would have a singleton class for SSE where I can call e.g. >>>>SSE::instance()->ethernet("eth0", ip,...) and my front-end can update >>>>the values. >>>> >>>>Can this work? >>>> >>>> >>>>--- >>>>Christian Gmeiner, MSc >>>> >>> >>> Why not? >>> >>> Several points >>> >>> 1. In there link there is an example to use it without polling, so just >>> use basic_io_device to check >>> for readability and then call recv >>> >>> So basically you don't need threads just implement event driven >>> handling in the event loop (see tutorial for examples) >>> >> >> This looks like the elegant solution I am looking for :) >> >> But... I don't get it up and running :/ >> >> I decided to go this way: >> >> #ifndef NETLINK_H_ >> #define NETLINK_H_ >> >> #include <booster/aio/basic_io_device.h> >> >> class Netlink : public booster::aio::basic_io_device >> { >> public: >> Netlink(); >> ~Netlink(); >> >> void read(booster::system::error_code const &e); >> >> private: >> char _buffer[4096]; >> }; >> >> #endif /* NETLINK_H_ */ >> >> >> And this is my main() >> >> // start cppcms service >> try >> { >> cppcms::service srv(argc, argv); >> >> booster::aio::io_service &io_srv = srv.get_io_service(); >> >> Netlink netlink; >> netlink.set_io_service(io_srv); >> netlink.on_readable(std::bind(&Netlink::read)); >> >> srv.applications_pool().mount(cppcms::applications_factory<Tssw>()); >> srv.run(); >> } >> catch (std::exception const &e) >> { >> std::cerr << e.what() << std::endl; >> } >> >> >> The big big problem is how should I use on_readable(..) ? The above example >> does >> not compile. >> >> ---- >> Christian Gmeiner, MSc >> >> ------------------------------------------------------------------------------ >> Don't let slow site performance ruin your business. Deploy New Relic APM >> Deploy New Relic app performance management and know exactly >> what is happening inside your Ruby, Python, PHP, Java, and .NET app >> Try New Relic at no cost today and get our sweet Data Nerd shirt too! >> http://p.sf.net/sfu/newrelic-dev2dev >> _______________________________________________ >> Cppcms-users mailing list >> Cpp...@li... >> https://lists.sourceforge.net/lists/listinfo/cppcms-users >> >> >> >> ------------------------------------------------------------------------------ >> Don't let slow site performance ruin your business. Deploy New Relic APM >> Deploy New Relic app performance management and know exactly >> what is happening inside your Ruby, Python, PHP, Java, and .NET app >> Try New Relic at no cost today and get our sweet Data Nerd shirt too! >> http://p.sf.net/sfu/newrelic-dev2dev >> _______________________________________________ >> Cppcms-users mailing list >> Cpp...@li... >> https://lists.sourceforge.net/lists/listinfo/cppcms-users >> |
From: Artyom B. <art...@ya...> - 2012-10-04 19:00:15
|
Just few words, booster::aio::io_service::post is used to execute something in the event loop "later" i.e. you give a callback and it would executed in the dispatch queue of the event loop, it is also important that it is thread safe. Post used for two reasons: 1. Make sure that the handler is not called right now but rather put into queue - it is very useful to prevent accidential recursions 2. When you need to execute something on non-thread safe class withing the event loop thread, as post is thread safe. i.e. if some event driven object like asyncrchonous app., aio socket etc. runs withing the event loop and you want to for example send something to socket form another thread, you can't do it directly as socket objects, application objects are not thread safe, so you POST the callback and you know that it would be called in the event loop rather than the thread In your case the callback of the "on_readable()" is already called from the event loop, so you don't really need to post() anything as you are already in the event loop, As SSE::handle should be called from the event loop and you are in the event loop the callback of "on_readable()" than instead: this->get_io_service().post(std::bind(&SSE::handle,this,....) You just call handle(something,ip) ... If you still want to post() (you can but not have to), once again, lambda: this->get_io_service().post([=,this]() { handler(something,ip) }); How to do it with bind? As I said before read : http://www.boost.org/doc/libs/1_51_0/libs/bind/bind.html Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ ----- Original Message ----- > From: Christian Gmeiner <chr...@gm...> > > I have looked quite deeply into post(..) usages, but I don't get it :/ > I have seen binder's - > what is the concept behind them? > > thanks > --- > Christian Gmeiner MSc > |