Add icon field to service, fix ping calculation, longer backoff for domain name resolution, make service deinit function
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
#define POLLRDHUP 0x2000
|
||||
#endif
|
||||
|
||||
uint8_t report_queued = 0;
|
||||
uint8_t report_queued = 1;
|
||||
uint64_t queued_time = 0;
|
||||
Vector services;
|
||||
Vector status_timeline; // of StatusPeroid*
|
||||
@@ -37,7 +37,7 @@ void* run_endpoint(void* endpoint) {
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(ret));
|
||||
queue_report((struct EndpointStatus){ self, DOWN, -1.0 });
|
||||
sleep(self->backoff);
|
||||
sleep(self->backoff*2); // sleep longer to avoid spamming for DNS lookup
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -50,9 +50,6 @@ void* run_endpoint(void* endpoint) {
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
struct timespec connect_start;
|
||||
clock_gettime(CLOCK_REALTIME_ALARM, &connect_start);
|
||||
|
||||
int ret = connect(fd, rp->ai_addr, rp->ai_addrlen);
|
||||
int error = 0;
|
||||
if (strcmp(self->scheme, "tcp") == 0) {
|
||||
@@ -103,15 +100,7 @@ void* run_endpoint(void* endpoint) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fd > 0) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_REALTIME_ALARM, &now);
|
||||
|
||||
double ping = (now.tv_sec - connect_start.tv_sec) * 1000.0 + (now.tv_nsec - connect_start.tv_nsec) / 1000000.0;
|
||||
|
||||
self->sockfd = fd;
|
||||
self->last_errno = 0;
|
||||
}
|
||||
self->sockfd = fd;
|
||||
}
|
||||
|
||||
if (self->sockfd < 0) {
|
||||
@@ -122,9 +111,8 @@ void* run_endpoint(void* endpoint) {
|
||||
queue_report((struct EndpointStatus){ self, DOWN, -1.0 });
|
||||
sleep(self->backoff);
|
||||
continue;
|
||||
}
|
||||
} else self->last_errno = 0;
|
||||
}
|
||||
|
||||
struct pollfd pfd = { .fd = self->sockfd, .events = POLLIN | POLLERR | POLLHUP | POLLRDHUP };
|
||||
int pollret = poll(&pfd, 1, (self->backoff > 0 ? self->backoff * 1000 : 10000));
|
||||
|
||||
@@ -138,19 +126,22 @@ void* run_endpoint(void* endpoint) {
|
||||
if (recv(self->sockfd, NULL, sizeof(NULL), MSG_DONTWAIT | MSG_PEEK) < 0) {
|
||||
close(self->sockfd);
|
||||
self->sockfd = -1;
|
||||
sleep(self->backoff);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pfd.revents & (POLLERR | POLLHUP | POLLRDHUP)) || pfd.events & POLLRDHUP) {
|
||||
if (pfd.revents & (POLLERR | POLLHUP | POLLRDHUP)) {
|
||||
close(self->sockfd);
|
||||
self->sockfd = -1;
|
||||
sleep(self->backoff);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(self->scheme, "udp") == 0 && send(self->sockfd, NULL, 0, 0) < 0) {
|
||||
close(self->sockfd);
|
||||
self->sockfd = -1;
|
||||
sleep(self->backoff);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -158,8 +149,17 @@ void* run_endpoint(void* endpoint) {
|
||||
time_t now = time(NULL);
|
||||
if (now - self->last_check >= self->backoff) {
|
||||
self->last_check = now;
|
||||
queue_report((struct EndpointStatus){ self, UP, self->last_ping });
|
||||
|
||||
double ping = 0.0;
|
||||
if (strcmp(self->scheme, "udp") != 0) {
|
||||
struct tcp_info info = {0}; socklen_t len = sizeof(info);
|
||||
if (getsockopt(self->sockfd, IPPROTO_TCP, TCP_INFO, &info, &len) == 0) {
|
||||
ping = info.tcpi_rtt / 1000.0;
|
||||
}
|
||||
}
|
||||
queue_report((struct EndpointStatus){ self, UP, ping });
|
||||
}
|
||||
sleep(self->backoff);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -268,25 +268,11 @@ uint8_t add_endpoint(struct Service* self, const char* uri) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum State get_state(struct Service** self) {
|
||||
Iterator it = vector_begin(&(*self)->endpoints);
|
||||
Iterator end = vector_end(&(*self)->endpoints);
|
||||
int up_count = 0; int total_count = (*self)->endpoints.size;
|
||||
for (; !iterator_equals(&it, &end); iterator_increment(&it)) {
|
||||
struct Endpoint* endpoint = *(struct Endpoint**)iterator_get(&it);
|
||||
if (endpoint->last_state == UP)
|
||||
up_count++;
|
||||
}
|
||||
if (up_count == total_count) return UP;
|
||||
else if (up_count == 0) return DOWN;
|
||||
else return PARTIAL;
|
||||
}
|
||||
|
||||
void report() {
|
||||
if (status_timeline.size + 1 >= status_timeline.capacity)
|
||||
vector_pop_front(&status_timeline); // remove (what should be) oldest entry
|
||||
|
||||
struct StatusPeroid* peroid = malloc(512);
|
||||
struct StatusPeroid* peroid = malloc(sizeof(struct StatusPeroid));
|
||||
peroid->time = queued_time;
|
||||
vector_setup(&peroid->server_statuses, services.size, sizeof(struct ServerStatus*));
|
||||
|
||||
@@ -305,7 +291,7 @@ struct ServerStatus* update_server_status(struct Service** self) {
|
||||
struct Service* service = *self;
|
||||
double pings[service->endpoints.size] = {};
|
||||
|
||||
struct ServerStatus* server_status = malloc(512);
|
||||
struct ServerStatus* server_status = malloc(sizeof(struct ServerStatus));
|
||||
server_status->service = service;
|
||||
enum State service_state = DOWN;
|
||||
|
||||
@@ -322,28 +308,43 @@ struct ServerStatus* update_server_status(struct Service** self) {
|
||||
pings[index] = estatus.ping = endpoint->last_ping;
|
||||
vector_push_back(&server_status->endpoint_statuses, &estatus);
|
||||
if (index == 0) service_state = endpoint->last_state;
|
||||
else if ((endpoint->last_state == DOWN && service_state == UP) || (endpoint->last_state == UP && service_state == DOWN))
|
||||
service_state = PARTIAL;
|
||||
else if (
|
||||
((endpoint->last_state == DOWN || endpoint->last_state == NONE) && service_state == UP) ||
|
||||
(endpoint->last_state == UP && (service_state == DOWN || service_state == NONE))
|
||||
) service_state = PARTIAL;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (service_state == NONE)
|
||||
service_state = DOWN;
|
||||
|
||||
size_t pings_len = index;
|
||||
double ping_sum = 0;
|
||||
double avg_ping;
|
||||
if (pings_len > 0) {
|
||||
for (int i = 0; i < sizeof(pings)/sizeof(double); i++)
|
||||
if (pings[i] >= 0) {
|
||||
ping_sum+=pings[i];
|
||||
pings_len--;
|
||||
}
|
||||
double avg_ping = 0.0;
|
||||
for (int i = 0; i < pings_len; i++)
|
||||
if (pings[i] >= 0)
|
||||
ping_sum+=pings[i];
|
||||
if (ping_sum != 0 || pings_len != 0)
|
||||
avg_ping = ping_sum / pings_len;
|
||||
} else avg_ping = -1.0;
|
||||
|
||||
server_status->state = service_state;
|
||||
server_status->ping = avg_ping;
|
||||
return server_status;
|
||||
}
|
||||
|
||||
void deinit_service(struct Service** self) {
|
||||
struct Service* service = *self;
|
||||
Iterator it = vector_begin(&service->endpoints);
|
||||
Iterator end = vector_end(&service->endpoints);
|
||||
for (; !iterator_equals(&it, &end); iterator_increment(&it)) {
|
||||
struct Endpoint* endpoint = *(struct Endpoint**)iterator_get(&it);
|
||||
endpoint->enabled = 0;
|
||||
int ret = pthread_join(endpoint->thread, NULL);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "Thread joining encountered an error: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
const char* state_text(enum State state) {
|
||||
switch (state) {
|
||||
case NONE: return "NONE";
|
||||
|
||||
@@ -30,6 +30,7 @@ void load_service(struct Service** self);
|
||||
uint8_t add_endpoint(struct Service* self, const char* uri);
|
||||
enum State get_state(struct Service** self);
|
||||
struct ServerStatus* update_server_status(struct Service** self);
|
||||
void deinit_service(struct Service** self);
|
||||
const char* state_text(enum State state);
|
||||
|
||||
struct StatusPeroid {
|
||||
@@ -71,6 +72,7 @@ struct Endpoint {
|
||||
struct Service {
|
||||
char* id;
|
||||
char* name;
|
||||
char* icon;
|
||||
char* text;
|
||||
Vector endpoints;
|
||||
enum State last_state;
|
||||
|
||||
Reference in New Issue
Block a user