~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/json_server/json_server.cc

  • Committer: Brian Aker
  • Date: 2011-07-12 23:34:13 UTC
  • mto: (2392.1.1 drizzle-autoconf)
  • mto: This revision was merged to the branch mainline in revision 2364.
  • Revision ID: brian@tangent.org-20110712233413-c8wwn3tw2p39g5t5
Fix memory leak in temporal and json server.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
 
22
22
#include <config.h>
 
23
 
 
24
#include <unistd.h>
 
25
#include <fcntl.h>
 
26
 
23
27
#include <drizzled/module/module.h>
24
28
#include <drizzled/module/context.h>
25
29
#include <drizzled/plugin/plugin.h>
26
30
#include <drizzled/plugin.h>
 
31
#include <drizzled/plugin/daemon.h>
27
32
#include <drizzled/sys_var.h>
28
33
#include <drizzled/gettext.h>
29
34
#include <drizzled/error.h>
38
43
#include <drizzled/constrained_value.h>
39
44
#include <evhttp.h>
40
45
#include <event.h>
41
 
#include <pthread.h>
42
46
#include <drizzled/execute.h>
43
47
#include <drizzled/sql/result_set.h>
44
48
 
46
50
#include <drizzled/plugin/client.h>
47
51
#include <drizzled/catalog/local.h>
48
52
 
 
53
#include <drizzled/pthread_globals.h>
 
54
#include <boost/bind.hpp>
 
55
 
 
56
 
49
57
#include <drizzled/version.h>
50
58
#include <plugin/json_server/json/json.h>
51
59
 
59
67
{
60
68
 
61
69
static port_constraint port;
62
 
struct event_base *base= NULL;
63
 
struct evhttp *httpd;
64
70
 
65
71
static in_port_t getPort(void)
66
72
{
222
228
  evhttp_send_reply(req, HTTP_OK, "OK", buf);
223
229
}
224
230
 
225
 
extern "C" void *libevent_thread(void*);
226
 
 
227
 
extern "C" void *libevent_thread(void*)
 
231
static void shutdown_event(int fd, short, void *arg)
 
232
{
 
233
  struct event_base *base= (struct event_base *)arg;
 
234
  event_base_loopbreak(base);
 
235
  close(fd);
 
236
}
 
237
 
 
238
 
 
239
static void run(struct event_base *base)
228
240
{
229
241
  internal::my_thread_init();
230
242
 
231
243
  event_base_dispatch(base);
232
 
  evhttp_free(httpd);
233
 
  return NULL;
234
244
}
235
245
 
 
246
 
 
247
class JsonServer : public drizzled::plugin::Daemon
 
248
{
 
249
private:
 
250
  JsonServer(const JsonServer &);
 
251
  JsonServer& operator=(const JsonServer &);
 
252
 
 
253
  drizzled::thread_ptr json_thread;
 
254
  in_port_t _port;
 
255
  struct evhttp *httpd;
 
256
  struct event_base *base;
 
257
  int wakeup_fd[2];
 
258
  struct event wakeup_event;
 
259
 
 
260
public:
 
261
  JsonServer(in_port_t port_arg) :
 
262
    drizzled::plugin::Daemon("JSON Server"),
 
263
    _port(port_arg),
 
264
    httpd(NULL),
 
265
    base(NULL)
 
266
  { }
 
267
 
 
268
  bool init()
 
269
  {
 
270
    if (pipe(wakeup_fd) < 0)
 
271
    {
 
272
      sql_perror("pipe");
 
273
      return false;
 
274
    }
 
275
 
 
276
    int returned_flags;
 
277
    if ((returned_flags= fcntl(wakeup_fd[0], F_GETFL, 0)) < 0)
 
278
    {
 
279
      sql_perror("fcntl:F_GETFL");
 
280
      return false;
 
281
    }
 
282
 
 
283
    if (fcntl(wakeup_fd[0], F_SETFL, returned_flags | O_NONBLOCK) < 0)
 
284
 
 
285
    {
 
286
      sql_perror("F_SETFL");
 
287
      return false;
 
288
    }
 
289
 
 
290
    if ((base= event_init()) == NULL)
 
291
    {
 
292
      sql_perror("event_init()");
 
293
      return false;
 
294
    }
 
295
 
 
296
    if ((httpd= evhttp_new(base)) == NULL)
 
297
    {
 
298
      sql_perror("evhttp_new()");
 
299
      return false;
 
300
    }
 
301
 
 
302
 
 
303
    if ((evhttp_bind_socket(httpd, "0.0.0.0", getPort())) == -1)
 
304
    {
 
305
      sql_perror("evhttp_bind_socket()");
 
306
      return false;
 
307
    }
 
308
 
 
309
    evhttp_set_cb(httpd, "/", process_root_request, NULL);
 
310
    evhttp_set_cb(httpd, "/0.1/version", process_api01_version_req, NULL);
 
311
    evhttp_set_cb(httpd, "/0.1/sql", process_api01_sql_req, NULL);
 
312
    evhttp_set_gencb(httpd, process_request, NULL);
 
313
 
 
314
    event_set(&wakeup_event, wakeup_fd[0], EV_READ | EV_PERSIST, shutdown_event, base);
 
315
    event_base_set(base, &wakeup_event);
 
316
    if (event_add(&wakeup_event, NULL) < 0)
 
317
    {
 
318
      sql_perror("event_add");
 
319
      return false;
 
320
    }
 
321
 
 
322
    json_thread.reset(new boost::thread((boost::bind(&run, base))));
 
323
 
 
324
    if (not json_thread)
 
325
      return false;
 
326
 
 
327
    return true;
 
328
  }
 
329
 
 
330
  ~JsonServer()
 
331
  {
 
332
    // If we can't write(), we will just muddle our way through the shutdown
 
333
    char buffer[1];
 
334
    buffer[0]= 4;
 
335
    if ((write(wakeup_fd[1], &buffer, 1)) == 1)
 
336
    {
 
337
      json_thread->join();
 
338
      evhttp_free(httpd);
 
339
      event_base_free(base);
 
340
    }
 
341
  }
 
342
};
 
343
 
236
344
static int json_server_init(drizzled::module::Context &context)
237
345
{
238
346
  context.registerVariable(new sys_var_constrained_value_readonly<in_port_t>("port", port));
239
347
 
240
 
  base= event_init();
241
 
  httpd= evhttp_new(base);
242
 
  if (httpd == NULL)
243
 
    return -1;
244
 
 
245
 
  int r= evhttp_bind_socket(httpd, "0.0.0.0", getPort());
246
 
 
247
 
  if (r != 0)
 
348
  JsonServer *server;
 
349
  context.add(server= new JsonServer(port));
 
350
 
 
351
  if (server and not server->init())
 
352
  {
248
353
    return -2;
249
 
 
250
 
  evhttp_set_cb(httpd, "/", process_root_request, NULL);
251
 
  evhttp_set_cb(httpd, "/0.1/version", process_api01_version_req, NULL);
252
 
  evhttp_set_cb(httpd, "/0.1/sql", process_api01_sql_req, NULL);
253
 
  evhttp_set_gencb(httpd, process_request, NULL);
254
 
 
255
 
  pthread_t libevent_loop_thread;
256
 
 
257
 
  pthread_create(&libevent_loop_thread, NULL, libevent_thread, NULL);
258
 
 
259
 
  return 0;
 
354
  }
 
355
 
 
356
  return bool(server) ? 0 : 1;
260
357
}
261
358
 
262
359
static void init_options(drizzled::module::option_context &context)
263
360
{
264
361
  context("port",
265
 
          po::value<port_constraint>(&port)->default_value(80),
266
 
          _("Port number to use for connection or 0 for default (port 80) "));
 
362
          po::value<port_constraint>(&port)->default_value(8086),
 
363
          _("Port number to use for connection or 0 for default (port 8086) "));
267
364
}
268
365
 
269
366
} /* namespace json_server */