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 {
00037 namespace plugin
00038 {
00039
00040 static std::vector<plugin::Listen *> listen_list;
00041 std::vector<plugin::Listen *> listen_fd_list;
00042 std::vector<pollfd> fd_list;
00043 uint32_t fd_count= 0;
00044 int wakeup_pipe[2];
00045
00046 ListenVector &Listen::getListenProtocols()
00047 {
00048 return listen_list;
00049 }
00050
00051 bool Listen::addPlugin(plugin::Listen *listen_obj)
00052 {
00053 listen_list.push_back(listen_obj);
00054 return false;
00055 }
00056
00057 void Listen::removePlugin(plugin::Listen *listen_obj)
00058 {
00059 listen_list.erase(std::remove(listen_list.begin(),
00060 listen_list.end(),
00061 listen_obj),
00062 listen_list.end());
00063 }
00064
00065 bool Listen::setup(void)
00066 {
00067 std::vector<plugin::Listen *>::iterator it;
00068
00069 for (it= listen_list.begin(); it < listen_list.end(); ++it)
00070 {
00071 std::vector<int> fds;
00072 std::vector<int>::iterator fd;
00073
00074 if ((*it)->getFileDescriptors(fds))
00075 {
00076 errmsg_printf(error::ERROR, _("Error getting file descriptors"));
00077 return true;
00078 }
00079
00080 fd_list.resize(fd_count + fds.size() + 1);
00081
00082 for (fd= fds.begin(); fd < fds.end(); ++fd)
00083 {
00084 fd_list[fd_count].fd= *fd;
00085 fd_list[fd_count].events= POLLIN | POLLERR;
00086 listen_fd_list.push_back(*it);
00087 fd_count++;
00088 }
00089 }
00090
00091 if (fd_count == 0)
00092 {
00093 errmsg_printf(error::ERROR,
00094 _("No sockets could be bound for listening"));
00095 return true;
00096 }
00097
00098
00099
00100
00101
00102 if (pipe(wakeup_pipe) == -1)
00103 {
00104 sql_perror("pipe()");
00105 return true;
00106 }
00107
00108 fd_list.resize(fd_count + 1);
00109
00110 fd_list[fd_count].fd= wakeup_pipe[0];
00111 fd_list[fd_count].events= POLLIN | POLLERR;
00112 fd_count++;
00113
00114 return false;
00115 }
00116
00117 Client *plugin::Listen::getClient(void)
00118 {
00119 int ready;
00120 plugin::Client *client;
00121
00122 while (1)
00123 {
00124 ready= poll(&fd_list[0], fd_count, -1);
00125 if (ready == -1)
00126 {
00127 if (errno != EINTR)
00128 {
00129 sql_perror("poll()");
00130 }
00131
00132 continue;
00133 }
00134 else if (ready == 0)
00135 continue;
00136
00137 for (uint32_t x= 0; x < fd_count; x++)
00138 {
00139 if (fd_list[x].revents != POLLIN)
00140 continue;
00141
00142
00143 if (x == fd_count - 1)
00144 {
00145
00146 for (x= 0; x < fd_count; x++)
00147 {
00148 (void) ::shutdown(fd_list[x].fd, SHUT_RDWR);
00149 (void) close(fd_list[x].fd);
00150 fd_list[x].fd= -1;
00151 }
00152
00153
00154 (void) close(wakeup_pipe[1]);
00155
00156 return NULL;
00157 }
00158
00159 if (!(client= listen_fd_list[x]->getClient(fd_list[x].fd)))
00160 continue;
00161
00162 return client;
00163 }
00164 }
00165 }
00166
00167 Client *plugin::Listen::getNullClient(void)
00168 {
00169 return new plugin::NullClient();
00170 }
00171
00172 void Listen::shutdown(void)
00173 {
00174 ssize_t ret= write(wakeup_pipe[1], "\0", 1);
00175 assert(ret == 1);
00176 }
00177
00178
00179 }
00180 }