Drizzled Public API Documentation

listen.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2008 Sun Microsystems, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include <config.h>
21 
22 #include <drizzled/errmsg_print.h>
23 #include <drizzled/error.h>
24 #include <drizzled/gettext.h>
25 #include <drizzled/plugin/listen.h>
26 #include <drizzled/plugin/listen.h>
27 #include <drizzled/plugin/null_client.h>
28 
29 #ifdef HAVE_SYS_SOCKET_H
30 #include <sys/socket.h>
31 #endif
32 
33 #include <poll.h>
34 
35 namespace drizzled {
36 namespace plugin {
37 
38 static std::vector<plugin::Listen*> listen_list;
39 std::vector<plugin::Listen*> listen_fd_list;
40 std::vector<pollfd> fd_list;
41 uint32_t fd_count= 0;
42 int wakeup_pipe[2];
43 
44 ListenVector& Listen::getListenProtocols()
45 {
46  return listen_list;
47 }
48 
50 {
51  listen_list.push_back(listen_obj);
52  return false;
53 }
54 
56 {
57  listen_list.erase(std::remove(listen_list.begin(), listen_list.end(), listen_obj), listen_list.end());
58 }
59 
61 {
62  BOOST_FOREACH(plugin::Listen* it, listen_list)
63  {
64  std::vector<int> fds;
65  if (it->getFileDescriptors(fds))
66  {
67  errmsg_printf(error::ERROR, _("Error getting file descriptors"));
68  return true;
69  }
70 
71  fd_list.resize(fd_count + fds.size() + 1);
72 
73  BOOST_FOREACH(int fd, fds)
74  {
75  fd_list[fd_count].fd= fd;
76  fd_list[fd_count].events= POLLIN | POLLERR;
77  listen_fd_list.push_back(it);
78  fd_count++;
79  }
80  }
81 
82  if (fd_count == 0)
83  {
84  errmsg_printf(error::ERROR, _("No sockets could be bound for listening"));
85  return true;
86  }
87 
88  /*
89  We need a pipe to wakeup the listening thread since some operating systems
90  are stupid. *cough* OSX *cough*
91  */
92  if (pipe(wakeup_pipe) == -1)
93  {
94  sql_perror("pipe()");
95  return true;
96  }
97 
98  fd_list.resize(fd_count + 1);
99 
100  fd_list[fd_count].fd= wakeup_pipe[0];
101  fd_list[fd_count].events= POLLIN | POLLERR;
102  fd_count++;
103 
104  return false;
105 }
106 
108 {
109  while (1)
110  {
111  int ready= poll(&fd_list[0], fd_count, -1);
112  if (ready == -1)
113  {
114  if (errno != EINTR)
115  {
116  sql_perror("poll()");
117  }
118  continue;
119  }
120  else if (ready == 0)
121  continue;
122 
123  for (uint32_t x= 0; x < fd_count; x++)
124  {
125  if (fd_list[x].revents != POLLIN)
126  continue;
127 
128  /* Check to see if the wakeup_pipe was written to. */
129  if (x == fd_count - 1)
130  {
131  /* Close all file descriptors now. */
132  for (x= 0; x < fd_count; x++)
133  {
134  (void) ::shutdown(fd_list[x].fd, SHUT_RDWR);
135  (void) close(fd_list[x].fd);
136  fd_list[x].fd= -1;
137  }
138 
139  /* wakeup_pipe[0] was closed in the for loop above. */
140  (void) close(wakeup_pipe[1]);
141 
142  return NULL;
143  }
144 
145  if (plugin::Client* client= listen_fd_list[x]->getClient(fd_list[x].fd))
146  return client;
147  }
148  }
149 }
150 
152 {
153  return new plugin::NullClient();
154 }
155 
157 {
158  ssize_t ret= write(wakeup_pipe[1], "\0", 1);
159  assert(ret == 1);
160 }
161 
162 } /* namespace plugin */
163 } /* namespace drizzled */
static bool addPlugin(Listen *)
Definition: listen.cc:49
static void shutdown()
Definition: listen.cc:156
static void removePlugin(Listen *)
Definition: listen.cc:55
static plugin::Client * getClient()
Definition: listen.cc:107
static bool setup(void)
Definition: listen.cc:60
static plugin::Client * getNullClient()
Definition: listen.cc:151
virtual bool getFileDescriptors(std::vector< int > &fds)=0