1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <string.h>
#include <limits.h>
#include <pthread.h>
#include "event2/event.h"
#include "event2/buffer.h"
#include "event2/http.h"
#include "http_healthcheck.h"
#include <MESA/MESA_prof_load.h>
struct http_status_ctx
{
pthread_t pthread;
struct event_base *base;
struct event *ev;
struct evhttp *http;
unsigned int enable;
unsigned int port;
char addr[PATH_MAX];
char path[PATH_MAX];
uint64_t is_error;
} g_ctx = {0};
static void http_callback(struct evhttp_request *req, void *arg)
{
evhttp_send_reply(req, HTTP_OK, "", NULL);
}
static void gc_callback(evutil_socket_t fd, short what, void *arg)
{
// do nothing
// add gc_callback to avoid event_base_dispatch blocking, handle event_base_loopbreak inmediately
}
static void *http_healthcheck_thread(void *arg)
{
struct timeval gc_delay = {0, 500 * 1000}; // Microseconds, we set 500 miliseconds here.
printf("[http_healthcheck_thread]: running (listen: %s:%d path: %s)\n", g_ctx.addr, g_ctx.port, g_ctx.path);
g_ctx.base = event_base_new();
if (g_ctx.base == NULL)
{
printf("[http_healthcheck_thread]: event_base_new failed\n");
goto end;
}
g_ctx.ev = event_new(g_ctx.base, -1, EV_PERSIST, gc_callback, NULL);
if (g_ctx.ev == NULL)
{
printf("[http_healthcheck_thread]: event_new failed\n");
goto end;
}
if (evtimer_add(g_ctx.ev, &gc_delay) < 0)
{
printf("[http_healthcheck_thread]: evtimer_add failed\n");
goto end;
}
g_ctx.http = evhttp_new(g_ctx.base);
if (evhttp_set_cb(g_ctx.http, g_ctx.path, http_callback, NULL) < 0)
{
printf("[http_healthcheck_thread]: evhttp_set_cb failed\n");
goto end;
}
if (evhttp_bind_socket(g_ctx.http, g_ctx.addr, g_ctx.port) < 0)
{
printf("[http_healthcheck_thread]: evhttp_bind_socket failed\n");
goto end;
}
event_base_dispatch(g_ctx.base);
end:
if (g_ctx.http)
{
evhttp_free(g_ctx.http);
}
if (g_ctx.ev)
{
event_free(g_ctx.ev);
}
if (g_ctx.base)
{
event_base_free(g_ctx.base);
}
printf("[http_healthcheck_thread]: exit\n");
return NULL;
}
void http_healthcheck_server_start(const char *profile)
{
MESA_load_profile_uint_def(profile, "http_healthcheck_server", "enable", &g_ctx.enable, 0);
MESA_load_profile_uint_def(profile, "http_healthcheck_server", "port", &g_ctx.port, 8080);
MESA_load_profile_string_def(profile, "http_healthcheck_server", "addr", g_ctx.addr, sizeof(g_ctx.addr), "127.0.0.1");
MESA_load_profile_string_def(profile, "http_healthcheck_server", "path", g_ctx.path, sizeof(g_ctx.path), "/status");
if (!g_ctx.enable)
{
return;
}
pthread_create(&g_ctx.pthread, NULL, http_healthcheck_thread, (void *)&g_ctx);
}
void http_healthcheck_server_stop()
{
if (g_ctx.enable)
{
event_base_loopbreak(g_ctx.base);
pthread_join(g_ctx.pthread, NULL);
}
}
|