]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/pollmplexer.cc
Merge pull request #7677 from rgacogne/dnsdist-logging-facility
[thirdparty/pdns.git] / pdns / pollmplexer.cc
index 4e6fd49ade47353e1b4543b2cc197aa281a7fae0..8e3e8b1d3a054ba6e5857cec87f4686c74bab43d 100644 (file)
@@ -1,14 +1,52 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 #include "mplexer.hh"
 #include "sstuff.hh"
 #include <iostream>
 #include <poll.h>
 #include "misc.hh"
-#include <boost/lexical_cast.hpp>
-#include "syncres.hh"
-#include "utility.hh" 
-#include "namespaces.hh"
 #include "namespaces.hh"
 
+FDMultiplexer* FDMultiplexer::getMultiplexerSilent()
+{
+  FDMultiplexer* ret = nullptr;
+  for(const auto& i : FDMultiplexer::getMultiplexerMap()) {
+    try {
+      ret = i.second();
+      return ret;
+    }
+    catch(const FDMultiplexerException& fe) {
+    }
+    catch(...) {
+    }
+  }
+  return ret;
+}
+
+
+class PollFDMultiplexer : public FDMultiplexer
+{
+public:
+  PollFDMultiplexer()
+  {}
+  virtual ~PollFDMultiplexer()
+  {
+  }
+
+  virtual int run(struct timeval* tv, int timeout=500) override;
+  virtual void getAvailableFDs(std::vector<int>& fds, int timeout) override;
+
+  virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) override;
+  virtual void removeFD(callbackmap_t& cbmap, int fd) override;
+
+  string getName() const override
+  {
+    return "poll";
+  }
+private:
+  vector<struct pollfd> preparePollFD() const;
+};
 
 static FDMultiplexer* make()
 {
@@ -22,80 +60,92 @@ static struct RegisterOurselves
   }
 } doIt;
 
-void PollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter)
+void PollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd)
 {
-  Callback cb;
-  cb.d_callback=toDo;
-  cb.d_parameter=parameter;
-  memset(&cb.d_ttd, 0, sizeof(cb.d_ttd));
-  if(cbmap.count(fd))
-    throw FDMultiplexerException("Tried to add fd "+lexical_cast<string>(fd)+ " to multiplexer twice");
-  cbmap[fd]=cb;
+  accountingAddFD(cbmap, fd, toDo, parameter, ttd);
 }
 
 void PollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
 {
-  if(d_inrun && d_iter->first==fd)  // trying to remove us!
-    d_iter++;
+  if(d_inrun && d_iter->d_fd==fd)  // trying to remove us!
+    ++d_iter;
 
   if(!cbmap.erase(fd))
-    throw FDMultiplexerException("Tried to remove unlisted fd "+lexical_cast<string>(fd)+ " from multiplexer");
+    throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
 }
 
-bool pollfdcomp(const struct pollfd& a, const struct pollfd& b)
+vector<struct pollfd> PollFDMultiplexer::preparePollFD() const
 {
-  return a.fd < b.fd;
-}
-
-int PollFDMultiplexer::run(struct timeval* now)
-{
-  if(d_inrun) {
-    throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
-  }
-  
   vector<struct pollfd> pollfds;
-  
+  pollfds.reserve(d_readCallbacks.size() + d_writeCallbacks.size());
+
   struct pollfd pollfd;
-  for(callbackmap_t::const_iterator i=d_readCallbacks.begin(); i != d_readCallbacks.end(); ++i) {
-    pollfd.fd = i->first;
+  for(const auto& cb : d_readCallbacks) {
+    pollfd.fd = cb.d_fd;
     pollfd.events = POLLIN;
     pollfds.push_back(pollfd);
   }
 
-  for(callbackmap_t::const_iterator i=d_writeCallbacks.begin(); i != d_writeCallbacks.end(); ++i) {
-    pollfd.fd = i->first;
+  for(const auto& cb : d_writeCallbacks) {
+    pollfd.fd = cb.d_fd;
     pollfd.events = POLLOUT;
     pollfds.push_back(pollfd);
   }
 
-  int ret=poll(&pollfds[0], pollfds.size(), 500);
-  Utility::gettimeofday(now, 0); // MANDATORY!
+  return pollfds;
+}
+
+void PollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
+{
+  auto pollfds = preparePollFD();
+  int ret = poll(&pollfds[0], pollfds.size(), timeout);
+
+  if (ret < 0 && errno != EINTR)
+    throw FDMultiplexerException("poll returned error: " + stringerror());
+
+  for(const auto& pollfd : pollfds) {
+    if (pollfd.revents == POLLIN || pollfd.revents == POLLOUT) {
+      fds.push_back(pollfd.fd);
+    }
+  }
+}
+
+int PollFDMultiplexer::run(struct timeval* now, int timeout)
+{
+  if(d_inrun) {
+    throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
+  }
+
+  auto pollfds = preparePollFD();
+
+  int ret=poll(&pollfds[0], pollfds.size(), timeout);
+  gettimeofday(now, 0); // MANDATORY!
   
   if(ret < 0 && errno!=EINTR)
     throw FDMultiplexerException("poll returned error: "+stringerror());
 
   d_iter=d_readCallbacks.end();
   d_inrun=true;
-  
-  for(unsigned int n = 0; n < pollfds.size(); ++n) {  
-    if(pollfds[n].revents == POLLIN) {
-      d_iter=d_readCallbacks.find(pollfds[n].fd);
+
+  for(const auto& pollfd : pollfds) {
+    if(pollfd.revents == POLLIN) {
+      d_iter=d_readCallbacks.find(pollfd.fd);
     
       if(d_iter != d_readCallbacks.end()) {
-        d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
+        d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
         continue; // so we don't refind ourselves as writable!
       }
     }
-    else if(pollfds[n].revents == POLLOUT) {
-      d_iter=d_writeCallbacks.find(pollfds[n].fd);
+    else if(pollfd.revents == POLLOUT) {
+      d_iter=d_writeCallbacks.find(pollfd.fd);
     
       if(d_iter != d_writeCallbacks.end()) {
-        d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
+        d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
       }
     }
   }
   d_inrun=false;
-  return 0;
+  return ret;
 }
 
 #if 0