-
-
Save luhenry/9674492 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/mono/utils/mono-counters-agent.c b/mono/utils/mono-counters-agent.c | |
index 76ce467..994150e 100644 | |
--- a/mono/utils/mono-counters-agent.c | |
+++ b/mono/utils/mono-counters-agent.c | |
@@ -18,12 +18,14 @@ | |
#include <sys/socket.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
+#include <sys/select.h> | |
#include "mono-counters.h" | |
#include "mono-counters-internals.h" | |
#include "mono-counters-agent.h" | |
#include "mono-time.h" | |
#include "mono-threads.h" | |
+#define MONO_COUNTERS_AGENT_PROTOCOL_VERSION (0 << 8 | 1) | |
/** | |
* Protocol : | |
@@ -51,31 +53,29 @@ typedef struct MonoCounterAgent { | |
static const char *inspector_ip; | |
static int inspector_port; | |
-static int frequency; | |
+static gint64 interval; | |
static GSList* counters; | |
static gboolean agent_running; | |
+static short current_index = 0; | |
+ | |
static int | |
parse_counters_all (MonoCounter* counter, void** args) | |
{ | |
- static short index = 0; | |
- | |
MonoCounterAgent* _counter = g_malloc(sizeof(MonoCounterAgent)); | |
_counter->counter = counter; | |
_counter->value = NULL; | |
- _counter->index = index; | |
+ _counter->index = current_index++; | |
counters = g_slist_append (counters, _counter); | |
- index += 1; | |
- | |
+ | |
return 1; | |
} | |
static void | |
parse_counters_names (const char *counters_names) | |
{ | |
- short index = 0; | |
gchar **names, **ptr; | |
if (!counters_names) | |
@@ -86,15 +86,15 @@ parse_counters_names (const char *counters_names) | |
for (ptr = names; *ptr; ++ptr) { | |
MonoCounterCategory category; | |
MonoCounter *counter; | |
- MonoCounterAgent *agent_counter; | |
+ MonoCounterAgent *counter_agent; | |
gchar **split = g_strsplit(*ptr, "/", 2); | |
if (!split[0] || !split[1]) { | |
g_warning ("Bad counter format '%s' use Category/Name", *ptr); | |
goto end; | |
} | |
- | |
+ | |
category = mono_counters_category_name_to_id (split [0]); | |
- if (!category) { | |
+ if (category < 0) { | |
g_warning ("Category %s not found", split [0]); | |
goto end; | |
} | |
@@ -105,11 +105,12 @@ parse_counters_names (const char *counters_names) | |
goto end; | |
} | |
- agent_counter = g_new0 (MonoCounterAgent, 1); | |
- agent_counter->counter = counter; | |
- agent_counter->index = index++; | |
+ counter_agent = g_new0 (MonoCounterAgent, 1); | |
+ counter_agent->counter = counter; | |
+ counter_agent->value = NULL; | |
+ counter_agent->index = current_index++; | |
- counters = g_slist_append (counters, agent_counter); | |
+ counters = g_slist_append (counters, counter_agent); | |
end: | |
g_strfreev(split); | |
@@ -142,7 +143,7 @@ static gboolean | |
write_buffer_to_socket (int fd, const char* buffer, size_t size) | |
{ | |
size_t sent = 0; | |
- | |
+ | |
while (sent < size) { | |
ssize_t res = send (fd, buffer + sent, size - sent, 0); | |
if (res <= 0) | |
@@ -153,92 +154,344 @@ write_buffer_to_socket (int fd, const char* buffer, size_t size) | |
return TRUE; | |
} | |
-static void* | |
-mono_counters_agent_sampling_thread (void* ptr) | |
+static gboolean | |
+read_socket_to_buffer (int fd, const char* buffer, size_t size) | |
+{ | |
+ size_t recvd = 0; | |
+ | |
+ while (recvd < size) { | |
+ ssize_t res = recv (fd, buffer + recvd, size - recvd, 0); | |
+ if (res <= 0) | |
+ return FALSE; | |
+ recvd += res; | |
+ } | |
+ | |
+ return TRUE; | |
+} | |
+ | |
+static gboolean | |
+write_counter_agent_header (int socketfd, MonoCounterAgent *counter_agent) | |
{ | |
+ int len = strlen (counter_agent->counter->name); | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&counter_agent->counter->category, 4) | |
+ || !write_buffer_to_socket (socketfd, (char*)&len, 4) | |
+ || !write_buffer_to_socket (socketfd, (char*) counter_agent->counter->name, len) | |
+ || !write_buffer_to_socket (socketfd, (char*)&counter_agent->counter->type, 4) | |
+ || !write_buffer_to_socket (socketfd, (char*)&counter_agent->counter->unit, 4) | |
+ || !write_buffer_to_socket (socketfd, (char*)&counter_agent->counter->variance, 4) | |
+ || !write_buffer_to_socket (socketfd, (char*)&counter_agent->index, 2)) | |
+ return FALSE; | |
+ | |
+ return TRUE; | |
+} | |
+ | |
+static gboolean | |
+write_counter_agent_headers (int socketfd) | |
+{ | |
+ short count = 0; | |
GSList *item; | |
+ | |
+ for (item = counters; item; item = item->next) | |
+ ++count; | |
+ | |
+ if (!write_buffer_to_socket (socketfd, (char*)&count, 2)) | |
+ return FALSE; | |
+ | |
+ for (item = counters; item; item = item->next) { | |
+ if (!write_counter_agent_header(socketfd, item->data)) | |
+ return FALSE; | |
+ } | |
+ | |
+ return TRUE; | |
+} | |
+ | |
+static gboolean | |
+write_counter_agent_value (int socketfd, MonoCounterAgent *counter_agent) | |
+{ | |
+ return TRUE; | |
+} | |
+ | |
+static gboolean | |
+do_hello (int socketfd) | |
+{ | |
+ char cmd = 0; | |
+ short version = MONO_COUNTERS_AGENT_PROTOCOL_VERSION; | |
+ | |
+ if (!write_buffer_to_socket (socketfd, (char*)&cmd, 1)) | |
+ return FALSE; | |
+ | |
+ if (!write_buffer_to_socket (socketfd, (char*)&version, 2)) | |
+ return FALSE; | |
+ | |
+ if (!write_counter_agent_headers (socketfd)) | |
+ return FALSE; | |
+ | |
+ return TRUE; | |
+} | |
+ | |
+static gboolean | |
+do_list_counters (int socketfd) | |
+{ | |
+ char cmd = 1; | |
+ | |
+ if (!write_buffer_to_socket (socketfd, (char*)&cmd, 1)) | |
+ return FALSE; | |
+ | |
+ if (!write_counter_agent_headers (socketfd)) | |
+ return FALSE; | |
+ | |
+ return TRUE; | |
+} | |
+ | |
+static gboolean | |
+do_add_counter (int socketfd) | |
+{ | |
+ char cmd = 2; | |
+ int len; | |
+ char *category, *name; | |
+ char status; | |
+ MonoCounterCategory category_id; | |
+ MonoCounter *counter; | |
+ MonoCounterAgent *counter_agent, *counter_agent_tmp; | |
+ gboolean already_exists; | |
+ GSList *item; | |
+ | |
+ if (!write_buffer_to_socket (socketfd, (char*)&cmd, 1)) | |
+ return FALSE; | |
+ | |
+ if (!read_socket_to_buffer(socketfd, (char*)&len, 4)) | |
+ return FALSE; | |
+ | |
+ category = g_malloc(len + 1); | |
+ if (!read_socket_to_buffer(socketfd, category, len)) | |
+ return FALSE; | |
+ category[len] = '\0'; | |
+ | |
+ if (!read_socket_to_buffer(socketfd, (char*)&len, 4)) | |
+ return FALSE; | |
+ | |
+ name = g_malloc(len + 1); | |
+ if (!read_socket_to_buffer(socketfd, name, len)) | |
+ return FALSE; | |
+ name[len] = '\0'; | |
+ | |
+ category_id = mono_counters_category_name_to_id(category); | |
+ if (category < 0) | |
+ status = MONO_COUNTERS_AGENT_STATUS_NOTFOUND; | |
+ else { | |
+ counter = mono_counters_get(category_id, name); | |
+ if (!counter) { | |
+ status = MONO_COUNTERS_AGENT_STATUS_NOTFOUND; | |
+ } else { | |
+ counter_agent = g_new0 (MonoCounterAgent, 1); | |
+ counter_agent->counter = counter; | |
+ counter_agent->value = NULL; | |
+ counter_agent->index = current_index++; | |
+ | |
+ if (!counters) { | |
+ counters = g_slist_append (NULL, counter_agent); | |
+ status = MONO_COUNTERS_AGENT_STATUS_OK; | |
+ } else { | |
+ for (item = counters, already_exists = FALSE; item && !already_exists; item = item->next) { | |
+ counter_agent_tmp = item->data; | |
+ if (counter_agent_tmp->counter->category == category_id && strcmp(counter_agent_tmp->counter->name, name) == 0) { | |
+ already_exists = TRUE; | |
+ } | |
+ } | |
+ | |
+ if (!already_exists) { | |
+ counters = g_slist_append (counters, counter_agent); | |
+ status = MONO_COUNTERS_AGENT_STATUS_OK; | |
+ } else { | |
+ g_free (counter_agent); | |
+ status = MONO_COUNTERS_AGENT_STATUS_EXISTING; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ g_free(category); | |
+ g_free(name); | |
+ | |
+ if (!write_buffer_to_socket(socketfd, &status, 1)) | |
+ return FALSE; | |
+ | |
+ if (status == MONO_COUNTERS_AGENT_STATUS_OK) { | |
+ if (!write_counter_agent_header(socketfd, counter_agent)) | |
+ return FALSE; | |
+ } | |
+ | |
+ return TRUE; | |
+} | |
+ | |
+static gboolean | |
+do_remove_counter (int socketfd) | |
+{ | |
+ char cmd = 3; | |
+ short index; | |
+ char status; | |
+ GSList *item; | |
+ MonoCounterAgent *counter_agent = NULL, *counter_agent_tmp; | |
+ | |
+ if (!write_buffer_to_socket (socketfd, (char*)&cmd, 1)) | |
+ return FALSE; | |
+ | |
+ if (!read_socket_to_buffer(socketfd, (char*)&index, 2)) | |
+ return FALSE; | |
+ | |
+ if (index < 0) { | |
+ g_slist_free(counters); | |
+ status = MONO_COUNTERS_AGENT_STATUS_OK; | |
+ } else { | |
+ for (item = counters; item; item = item->next) { | |
+ counter_agent_tmp = item->data; | |
+ if (counter_agent_tmp->index == index) { | |
+ counter_agent = counter_agent_tmp; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (counter_agent) { | |
+ g_slist_remove (counters, counter_agent); | |
+ g_free (counter_agent); | |
+ | |
+ status = MONO_COUNTERS_AGENT_STATUS_OK; | |
+ } else { | |
+ status = MONO_COUNTERS_AGENT_STATUS_NOTFOUND; | |
+ } | |
+ } | |
+ | |
+ return write_buffer_to_socket(socketfd, &status, 1); | |
+} | |
+ | |
+static gboolean | |
+do_sampling (int socketfd) | |
+{ | |
+ char cmd = 4; | |
char buffer[8]; | |
- int socketfd = -1; | |
- short count = 0; | |
+ GSList *item; | |
+ MonoCounterAgent *counter_agent; | |
+ | |
+ if (!write_buffer_to_socket (socketfd, (char*)&cmd, 1)) | |
+ return FALSE; | |
+ | |
+ gint64 timestamp = mono_100ns_datetime (); | |
+ if (!write_buffer_to_socket (socketfd, (char*)×tamp, 8)) | |
+ return FALSE; | |
+ | |
+ for (item = counters; item; item = item->next) { | |
+ counter_agent = item->data; | |
+ | |
+ if (!counter_agent) | |
+ continue; | |
+ | |
+ int size = mono_counters_size (counter_agent->counter); | |
+ if (size < 0) | |
+ return FALSE; | |
+ | |
+ if (mono_counters_sample (counter_agent->counter, buffer, size) != size) | |
+ return FALSE; | |
+ | |
+ if (!counter_agent->value) | |
+ counter_agent->value = g_malloc (size); | |
+ else if (memcmp (counter_agent->value, buffer, size) == 0) | |
+ continue; | |
+ | |
+ memcpy (counter_agent->value, buffer, size); | |
+ | |
+ if (!write_buffer_to_socket (socketfd, (char*)&counter_agent->index, 2) | |
+ || !write_buffer_to_socket (socketfd, (char*)&size, 2) | |
+ || !write_buffer_to_socket (socketfd, (char*) buffer, size)) | |
+ return FALSE; | |
+ } | |
+ | |
+ short end = -1; | |
+ if (!write_buffer_to_socket (socketfd, (char*)&end, 2)) | |
+ return FALSE; | |
+ | |
+ return TRUE; | |
+} | |
+ | |
+static void* | |
+mono_counters_agent_sampling_thread (void* ptr) | |
+{ | |
+ int socketfd = -1, ret; | |
struct sockaddr_in inspector_addr; | |
- | |
+ struct timeval timeout; | |
+ fd_set socketfd_set; | |
+ gint64 last_sampling = 0, now; | |
+ char cmd; | |
+ | |
if ((socketfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { | |
g_warning ("mono-counters-agent: error with socket : %s", strerror (errno)); | |
return NULL; | |
} | |
- | |
+ | |
memset (&inspector_addr, 0, sizeof (inspector_addr)); | |
- | |
+ | |
inspector_addr.sin_family = AF_INET; | |
inspector_addr.sin_port = htons (inspector_port); | |
- | |
+ | |
if (!inet_pton (AF_INET, inspector_ip, &inspector_addr.sin_addr)) { | |
g_warning ("mono-counters-agent: error with inet_pton : %s", strerror (errno)); | |
goto cleanup; | |
} | |
- | |
- if (connect(socketfd, (struct sockaddr*)&inspector_addr, sizeof(inspector_addr)) < 0) { | |
+ | |
+ if (connect (socketfd, (struct sockaddr*)&inspector_addr, sizeof(inspector_addr)) < 0) { | |
g_warning ("mono-counters-agent: error with connect : %s", strerror(errno)); | |
goto cleanup; | |
} | |
- for (item = counters; item; item = item->next) | |
- ++count; | |
+ FD_ZERO (&socketfd_set); | |
- if (!write_buffer_to_socket (socketfd, (char*)&count, 2)) | |
+ if (!do_hello(socketfd)) | |
goto cleanup; | |
- for (item = counters; item; item = item->next) { | |
- MonoCounterAgent* counter = item->data; | |
- | |
- int len = strlen (counter->counter->name); | |
- | |
- if (!write_buffer_to_socket(socketfd, (char*)&counter->counter->category, 4) | |
- || !write_buffer_to_socket (socketfd, (char*)&len, 4) | |
- || !write_buffer_to_socket (socketfd, (char*)counter->counter->name, len) | |
- || !write_buffer_to_socket (socketfd, (char*)&counter->counter->type, 4) | |
- || !write_buffer_to_socket (socketfd, (char*)&counter->counter->unit, 4) | |
- || !write_buffer_to_socket (socketfd, (char*)&counter->counter->variance, 4) | |
- || !write_buffer_to_socket (socketfd, (char*)&counter->index, 2)) | |
- goto cleanup; | |
- } | |
- | |
for (;;) { | |
- gint64 timestamp = mono_100ns_ticks (); | |
- if (!write_buffer_to_socket (socketfd, (char*)×tamp, 8)) | |
- goto cleanup; | |
+ now = mono_100ns_datetime(); | |
+ if (last_sampling == 0 || now > last_sampling + interval * 10000) { | |
+ timeout.tv_sec = 0; | |
+ timeout.tv_usec = 0; | |
+ } else { | |
+ timeout.tv_sec = ((last_sampling + interval * 10000 - now) / 10) / 1000000; | |
+ timeout.tv_usec = ((last_sampling + interval * 10000 - now) / 10) % 1000000; | |
+ } | |
- for (item = counters; item; item = item->next) { | |
- MonoCounterAgent* counter = item->data; | |
+ FD_SET (socketfd, &socketfd_set); | |
- if (!counter) | |
+ if ((ret = select (socketfd + 1, &socketfd_set, NULL, NULL, &timeout)) < 0) { | |
+ if (errno == EINTR) | |
continue; | |
- int size = mono_counters_size (counter->counter); | |
- if (size < 0) | |
- goto cleanup; | |
- | |
- if (mono_counters_sample (counter->counter, buffer, size) != size) | |
+ g_warning ("mono-counters-agent: error with select : %s", strerror(errno)); | |
+ goto cleanup; | |
+ } | |
+ | |
+ if (ret == 0) { | |
+ if (!do_sampling(socketfd)) | |
goto cleanup; | |
- | |
- if (!counter->value) | |
- counter->value = g_malloc (size); | |
- else if (memcmp (counter->value, buffer, size) == 0) | |
- continue; | |
- | |
- memcpy (counter->value, buffer, size); | |
- | |
- if (!write_buffer_to_socket (socketfd, (char*)&counter->index, 2) | |
- || !write_buffer_to_socket (socketfd, (char*)&size, 2) | |
- || !write_buffer_to_socket (socketfd, (char*) buffer, size)) | |
+ | |
+ last_sampling = mono_100ns_datetime(); | |
+ } else { | |
+ if (!read_socket_to_buffer(socketfd, (char*)&cmd, 1)) | |
goto cleanup; | |
- } | |
- | |
- short end = -1; | |
- if (!write_buffer_to_socket (socketfd, (char*)&end, 2)) | |
- goto cleanup; | |
- usleep (1000000 / frequency); | |
+ switch (cmd) { | |
+ case 0: | |
+ if (!do_list_counters(socketfd)) | |
+ goto cleanup; | |
+ break; | |
+ case 1: | |
+ if (!do_add_counter(socketfd)) | |
+ goto cleanup; | |
+ break; | |
+ case 2: | |
+ if (!do_remove_counter(socketfd)) | |
+ goto cleanup; | |
+ break; | |
+ } | |
+ } | |
} | |
cleanup: | |
@@ -266,15 +519,15 @@ parse_configuration (const gchar* configuration) | |
} else if (g_str_has_prefix (opt, "counters=")) { | |
opt = strchr (opt, '=') + 1; | |
counters_names = g_strdup(opt); | |
- } else if (g_str_has_prefix (opt, "frequency=")) { | |
+ } else if (g_str_has_prefix (opt, "interval=")) { | |
opt = strchr (opt, '=') + 1; | |
- frequency = strtol (opt, NULL, 10); | |
+ interval = strtol (opt, NULL, 10); | |
} | |
} | |
- | |
+ | |
parse_counters_names(counters_names); | |
parse_address(address); | |
- | |
+ | |
g_free((void*)counters_names); | |
g_free((void*)address); | |
g_strfreev(opts); | |
diff --git a/mono/utils/mono-counters-agent.h b/mono/utils/mono-counters-agent.h | |
index 1f124b4..b5b4c35 100644 | |
--- a/mono/utils/mono-counters-agent.h | |
+++ b/mono/utils/mono-counters-agent.h | |
@@ -3,6 +3,13 @@ | |
#include "mono-compiler.h" | |
+enum { | |
+ MONO_COUNTERS_AGENT_STATUS_OK, | |
+ MONO_COUNTERS_AGENT_STATUS_NOK, | |
+ MONO_COUNTERS_AGENT_STATUS_NOTFOUND, | |
+ MONO_COUNTERS_AGENT_STATUS_EXISTING | |
+}; | |
+ | |
void mono_counters_agent_start (const char *args) MONO_INTERNAL; | |
#endif /* __MONO_COUNTERS_AGENTS_H__ */ | |
\ No newline at end of file | |
diff --git a/mono/utils/mono-counters.c b/mono/utils/mono-counters.c | |
index 0ad160f..b788d08 100644 | |
--- a/mono/utils/mono-counters.c | |
+++ b/mono/utils/mono-counters.c | |
@@ -401,7 +401,7 @@ mono_counters_size (MonoCounter* counter) | |
#if SIZEOF_VOID_P == 8 | |
case MONO_COUNTER_TYPE_WORD: | |
#endif | |
- case MONO_COUNTER_DOUBLE: | |
+ case MONO_COUNTER_TYPE_DOUBLE: | |
return 8; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment