GraphChi  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros
chi_httpadmin.hpp
1 /*
2  * chi_httpadmin.hpp
3  * graphchi_graphprocessing.π
4  *
5  * Created by Aapo Kyrola on 6/8/12.
6  * Copyright 2012 Carnegie Mellon University. All rights reserved.
7  *
8  */
9 
10 #ifndef CHI_HTTPADMIN_DEF
11 #define CHI_HTTPADMIN_DEF
12 
13 #include <assert.h>
14 #include <string.h>
15 #include <time.h>
16 #include <stdarg.h>
17 
18 #include "external/vpiotr-mongoose-cpp/mongoose.h"
19 
20 extern "C" {
21 #include "external/vpiotr-mongoose-cpp/mongoose.c"
22 }
23 namespace graphchi {
24 
25  static const char *ajax_reply_start =
26  "HTTP/1.1 200 OK\r\n"
27  "Cache: no-cache\r\n"
28  "Content-Type: application/x-javascript\r\n"
29  "\r\n";
30 
31  static const char *options[] = {
32  "document_root", "conf/adminhtml",
33  "listening_ports", "3333",
34  "num_threads", "1",
35  NULL
36  };
37 
38  static void get_qsvar(const struct mg_request_info *request_info,
39  const char *name, char *dst, size_t dst_len) {
40  const char *qs = request_info->query_string;
41  mg_get_var(qs, strlen(qs == NULL ? "" : qs), name, dst, dst_len);
42  }
43 
44  // If "callback" param is present in query string, this is JSONP call.
45  // Return 1 in this case, or 0 if "callback" is not specified.
46  // Wrap an output in Javascript function call.
47  static int handle_jsonp(struct mg_connection *conn,
48  const struct mg_request_info *request_info) {
49  char cb[64];
50 
51  get_qsvar(request_info, "callback", cb, sizeof(cb));
52  if (cb[0] != '\0') {
53  mg_printf(conn, "%s(", cb);
54  }
55 
56  return cb[0] == '\0' ? 0 : 1;
57  }
58 
59  template <typename ENGINE>
60  static void ajax_send_message(struct mg_connection *conn,
61  const struct mg_request_info *request_info) {
62  int is_jsonp;
63 
64  ENGINE * engine = (ENGINE*) request_info->user_data;
65 
66  mg_printf(conn, "%s", ajax_reply_start);
67  is_jsonp = handle_jsonp(conn, request_info);
68 
69 
70  std::string json_info = engine->get_info_json();
71  const char * cstr = json_info.c_str();
72  int len = (int)strlen(cstr);
73 
74  //mg_printf(conn, "%s", json_info.c_str());
75  // Send read bytes to the client, exit the loop on error
76  int num_written = 0;
77 
78  while (len > 0) {
79  if ((num_written = mg_write(conn, cstr, (size_t)len)) != len)
80  break;
81  len -= num_written;
82  cstr += num_written;
83  }
84 
85  if (is_jsonp) {
86  mg_printf(conn, "%s", ")");
87  }
88  }
89 
90 
91 
92 
93  template <typename ENGINE>
94  static void *event_handler(enum mg_event event,
95  struct mg_connection *conn,
96  const struct mg_request_info *request_info) {
97  void *processed = (void*) "yes";
98 
99  if (event == MG_NEW_REQUEST) {
100  if (strcmp(request_info->uri, "/ajax/getinfo") == 0) {
101  ajax_send_message<ENGINE>(conn, request_info);
102  } else if (strcmp(request_info->uri, "/ajax/getinfo2") == 0) {
103 
104  } else {
105  // No suitable handler found, mark as not processed. Mongoose will
106  // try to serve the request.
107  processed = NULL;
108  }
109  } else {
110  processed = NULL;
111  }
112 
113  return processed;
114  }
115 
116 
117  template <typename ENGINE>
118  void start_httpadmin(ENGINE * engine) {
119  struct mg_context *ctx;
120 
121  ctx = mg_start(&event_handler<ENGINE>, (void*)engine, options);
122  assert(ctx != NULL);
123  std::cout << "Started HTTP admin server. " << std::endl;
124  }
125 
126 
127 };
128 
129 #endif
130