From: Bert Hubert Date: Fri, 9 Oct 2009 13:33:04 +0000 (+0000) Subject: solaris 9 /dev/poll mplexer support X-Git-Tag: rec-3.2~118 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=781d550af025f9e972d777fc9e8fb3d5fbd35e21;p=pdns solaris 9 /dev/poll mplexer support git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1421 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/devpollmplexer.cc b/pdns/devpollmplexer.cc new file mode 100644 index 000000000..8531c06e1 --- /dev/null +++ b/pdns/devpollmplexer.cc @@ -0,0 +1,156 @@ +#include +#include "mplexer.hh" +#include "sstuff.hh" +#include +#include +#include "misc.hh" +#include +#include "syncres.hh" + +using namespace boost; +using namespace std; + +class DevPollFDMultiplexer : public FDMultiplexer +{ +public: + DevPollFDMultiplexer(); + virtual ~DevPollFDMultiplexer() + { + close(d_devpollfd); + } + + virtual int run(struct timeval* tv); + + virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter); + virtual void removeFD(callbackmap_t& cbmap, int fd); + string getName() + { + return "/dev/poll"; + } +private: + int d_devpollfd; +}; + + +static FDMultiplexer* makeDevPoll() +{ + return new DevPollFDMultiplexer(); +} + +static struct DevPollRegisterOurselves +{ + DevPollRegisterOurselves() { + FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeDevPoll)); // priority 0! + } +} doItDevPoll; + + +//int DevPollFDMultiplexer::s_maxevents=1024; +DevPollFDMultiplexer::DevPollFDMultiplexer() +{ + d_devpollfd=open("/dev/poll", O_RDWR); + if(d_devpollfd < 0) + throw FDMultiplexerException("Setting up /dev/poll: "+stringerror()); + +} + +void DevPollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter) +{ + accountingAddFD(cbmap, fd, toDo, parameter); + + struct pollfd devent; + devent.fd=fd; + devent.events= (&cbmap == &d_readCallbacks) ? POLLIN : POLLOUT; + devent.revents = 0; + + if(write(d_devpollfd, &devent, sizeof(devent)) != sizeof(devent)) { + cbmap.erase(fd); + throw FDMultiplexerException("Adding fd to /dev/poll/ set: "+stringerror()); + } +} + +void DevPollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd) +{ + if(!cbmap.erase(fd)) + throw FDMultiplexerException("Tried to remove unlisted fd "+lexical_cast(fd)+ " from multiplexer"); + + struct pollfd devent; + devent.fd=fd; + devent.events= POLLREMOVE; + devent.revents = 0; + + if(write(d_devpollfd, &devent, sizeof(devent)) != sizeof(devent)) { + cbmap.erase(fd); + throw FDMultiplexerException("Removing fd from epoll set: "+stringerror()); + } +} + +int DevPollFDMultiplexer::run(struct timeval* now) +{ + if(d_inrun) { + throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n"); + } + struct dvpoll dvp; + dvp.dp_nfds = d_readCallbacks.size() + d_writeCallbacks.size(); + dvp.dp_fds = new pollfd[dvp.dp_nfds]; + dvp.dp_timeout = 500; + int ret=ioctl(d_devpollfd, DP_POLL, &dvp); + gettimeofday(now,0); + + if(ret < 0 && errno!=EINTR) + throw FDMultiplexerException("/dev/poll returned error: "+stringerror()); + + if(ret < 1) // thanks AB! + return 0; + + d_inrun=true; + for(int n=0; n < ret; ++n) { + d_iter=d_readCallbacks.find(dvp.dp_fds[n].fd); + + if(d_iter != d_readCallbacks.end()) { + d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter); + continue; // so we don't refind ourselves as writable! + } + d_iter=d_writeCallbacks.find(dvp.dp_fds[n].fd); + + if(d_iter != d_writeCallbacks.end()) { + d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter); + } + } + delete[] dvp.dp_fds; + d_inrun=false; + return 0; +} + +#if 0 +void acceptData(int fd, funcparam_t& parameter) +{ + cout<<"Have data on fd "<(parameter); + string packet; + IPEndpoint rem; + sock->recvFrom(packet, rem); + cout<<"Received "<