00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/errmsg_print.h>
00023 #include <drizzled/error.h>
00024 #include <drizzled/gettext.h>
00025 #include <drizzled/plugin/listen.h>
00026 #include <drizzled/plugin/listen.h>
00027 #include <drizzled/plugin/null_client.h>
00028
00029 #ifdef HAVE_SYS_SOCKET_H
00030 #include <sys/socket.h>
00031 #endif
00032
00033 #include <poll.h>
00034
00035 namespace drizzled {
00036 namespace plugin {
00037
00038 static std::vector<plugin::Listen*> listen_list;
00039 std::vector<plugin::Listen*> listen_fd_list;
00040 std::vector<pollfd> fd_list;
00041 uint32_t fd_count= 0;
00042 int wakeup_pipe[2];
00043
00044 ListenVector& Listen::getListenProtocols()
00045 {
00046 return listen_list;
00047 }
00048
00049 bool Listen::addPlugin(plugin::Listen *listen_obj)
00050 {
00051 listen_list.push_back(listen_obj);
00052 return false;
00053 }
00054
00055 void Listen::removePlugin(plugin::Listen *listen_obj)
00056 {
00057 listen_list.erase(std::remove(listen_list.begin(), listen_list.end(), listen_obj), listen_list.end());
00058 }
00059
00060 bool Listen::setup()
00061 {
00062 BOOST_FOREACH(plugin::Listen* it, listen_list)
00063 {
00064 std::vector<int> fds;
00065 if (it->getFileDescriptors(fds))
00066 {
00067 errmsg_printf(error::ERROR, _("Error getting file descriptors"));
00068 return true;
00069 }
00070
00071 fd_list.resize(fd_count + fds.size() + 1);
00072
00073 BOOST_FOREACH(int fd, fds)
00074 {
00075 fd_list[fd_count].fd= fd;
00076 fd_list[fd_count].events= POLLIN | POLLERR;
00077 listen_fd_list.push_back(it);
00078 fd_count++;
00079 }
00080 }
00081
00082 if (fd_count == 0)
00083 {
00084 errmsg_printf(error::ERROR, _("No sockets could be bound for listening"));
00085 return true;
00086 }
00087
00088
00089
00090
00091
00092 if (pipe(wakeup_pipe) == -1)
00093 {
00094 sql_perror("pipe()");
00095 return true;
00096 }
00097
00098 fd_list.resize(fd_count + 1);
00099
00100 fd_list[fd_count].fd= wakeup_pipe[0];
00101 fd_list[fd_count].events= POLLIN | POLLERR;
00102 fd_count++;
00103
00104 return false;
00105 }
00106
00107 Client *plugin::Listen::getClient()
00108 {
00109 while (1)
00110 {
00111 int ready= poll(&fd_list[0], fd_count, -1);
00112 if (ready == -1)
00113 {
00114 if (errno != EINTR)
00115 {
00116 sql_perror("poll()");
00117 }
00118 continue;
00119 }
00120 else if (ready == 0)
00121 continue;
00122
00123 for (uint32_t x= 0; x < fd_count; x++)
00124 {
00125 if (fd_list[x].revents != POLLIN)
00126 continue;
00127
00128
00129 if (x == fd_count - 1)
00130 {
00131
00132 for (x= 0; x < fd_count; x++)
00133 {
00134 (void) ::shutdown(fd_list[x].fd, SHUT_RDWR);
00135 (void) close(fd_list[x].fd);
00136 fd_list[x].fd= -1;
00137 }
00138
00139
00140 (void) close(wakeup_pipe[1]);
00141
00142 return NULL;
00143 }
00144
00145 if (plugin::Client* client= listen_fd_list[x]->getClient(fd_list[x].fd))
00146 return client;
00147 }
00148 }
00149 }
00150
00151 Client *plugin::Listen::getNullClient()
00152 {
00153 return new plugin::NullClient();
00154 }
00155
00156 void Listen::shutdown()
00157 {
00158 ssize_t ret= write(wakeup_pipe[1], "\0", 1);
00159 assert(ret == 1);
00160 }
00161
00162 }
00163 }