* Pass to event_add only copies of struct timeval to avoid timing problemstags/0.2.7
@@ -147,6 +147,21 @@ IF(ENABLE_PROFILING MATCHES "ON") | |||
ENDIF(ENABLE_PROFILING MATCHES "ON") | |||
IF(ENABLE_GPERF_TOOLS MATCHES "ON") | |||
FIND_PATH(GPERF_INCLUDE google/profiler.h PATHS /opt/include | |||
/usr/include | |||
/usr/local/include | |||
DOC "Path where google perftools includes can be found") | |||
INCLUDE_DIRECTORIES("${GPERF_INCLUDE}") | |||
FIND_LIBRARY(GPERF_LIBRARY NAMES profiler PATHS /lib | |||
/opt/lib | |||
/usr/lib | |||
/usr/local/lib | |||
DOC "Path where the gperf library can be found") | |||
IF(NOT GPERF_LIBRARY) | |||
MESSAGE(FATAL_ERROR "gperf tools support is enabled but not found in system") | |||
ENDIF(NOT GPERF_LIBRARY) | |||
GET_FILENAME_COMPONENT(GPERF_PATH "${GPERF_LIBRARY}" PATH) | |||
LINK_DIRECTORIES("${GPERF_PATH}") | |||
SET(WITH_GPERF_TOOLS 1) | |||
ENDIF(ENABLE_GPERF_TOOLS MATCHES "ON") | |||
@@ -429,6 +444,7 @@ ADD_EXECUTABLE(rspamd ${RSPAMDSRC} ${CONTRIBSRC} ${TOKENIZERSSRC} | |||
${CLASSIFIERSSRC} ${PLUGINSSRC} ${YACC_OUTPUT} | |||
${LEX_OUTPUT}) | |||
SET_TARGET_PROPERTIES(rspamd PROPERTIES LINKER_LANGUAGE C) | |||
SET_TARGET_PROPERTIES(rspamd PROPERTIES COMPILE_FLAGS "-DRSPAMD_MAIN") | |||
SET_TARGET_PROPERTIES(rspamd PROPERTIES VERSION ${RSPAMD_VERSION}) | |||
IF(ENABLE_PERL MATCHES "ON") |
@@ -269,6 +269,10 @@ | |||
#define HAVE_SETLOCALE 1 | |||
#endif | |||
#ifdef WITH_GPERF_TOOLS | |||
#include <google/profiler.h> | |||
#endif | |||
#include <errno.h> | |||
#include <signal.h> | |||
#include <event.h> |
@@ -44,6 +44,7 @@ write_buffers (int fd, rspamd_io_dispatcher_t *d) | |||
GList *cur; | |||
GError *err; | |||
rspamd_buffer_t *buf; | |||
struct timeval *ntv; | |||
ssize_t r; | |||
/* Fix order */ | |||
@@ -87,7 +88,9 @@ write_buffers (int fd, rspamd_io_dispatcher_t *d) | |||
/* Wait for other event */ | |||
event_del (d->ev); | |||
event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); | |||
event_add (d->ev, d->tv); | |||
ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); | |||
memcpy (ntv, d->tv, sizeof (struct timeval)); | |||
event_add (d->ev, ntv); | |||
return; | |||
} | |||
cur = g_list_next (cur); | |||
@@ -111,13 +114,17 @@ write_buffers (int fd, rspamd_io_dispatcher_t *d) | |||
event_del (d->ev); | |||
event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); | |||
event_add (d->ev, d->tv); | |||
ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); | |||
memcpy (ntv, d->tv, sizeof (struct timeval)); | |||
event_add (d->ev, ntv); | |||
} | |||
else { | |||
/* Plan other write event */ | |||
event_del (d->ev); | |||
event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); | |||
event_add (d->ev, d->tv); | |||
ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); | |||
memcpy (ntv, d->tv, sizeof (struct timeval)); | |||
event_add (d->ev, ntv); | |||
} | |||
} | |||
@@ -257,6 +264,7 @@ dispatcher_cb (int fd, short what, void *arg) | |||
{ | |||
rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *)arg; | |||
GError *err; | |||
struct timeval *ntv; | |||
msg_debug ("dispatcher_cb: in dispatcher callback, what: %d, fd: %d", (int)what, fd); | |||
@@ -272,7 +280,9 @@ dispatcher_cb (int fd, short what, void *arg) | |||
if (d->out_buffers == NULL) { | |||
event_del (d->ev); | |||
event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); | |||
event_add (d->ev, d->tv); | |||
ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); | |||
memcpy (ntv, d->tv, sizeof (struct timeval)); | |||
event_add (d->ev, ntv); | |||
} | |||
else { | |||
write_buffers (fd, d); | |||
@@ -293,6 +303,7 @@ rspamd_create_dispatcher (int fd, enum io_policy policy, | |||
struct timeval *tv, void *user_data) | |||
{ | |||
rspamd_io_dispatcher_t *new; | |||
struct timeval *ntv; | |||
if (fd == -1) { | |||
return NULL; | |||
@@ -320,7 +331,9 @@ rspamd_create_dispatcher (int fd, enum io_policy policy, | |||
new->fd = fd; | |||
event_set (new->ev, fd, EV_WRITE, dispatcher_cb, (void *)new); | |||
event_add (new->ev, new->tv); | |||
ntv = memory_pool_alloc (new->pool, sizeof (struct timeval)); | |||
memcpy (ntv, new->tv, sizeof (struct timeval)); | |||
event_add (new->ev, ntv); | |||
return new; | |||
} | |||
@@ -378,6 +391,7 @@ rspamd_dispatcher_write (rspamd_io_dispatcher_t *d, | |||
size_t len, gboolean delayed, gboolean allocated) | |||
{ | |||
rspamd_buffer_t *newbuf; | |||
struct timeval *ntv; | |||
newbuf = memory_pool_alloc (d->pool, sizeof (rspamd_buffer_t)); | |||
if (!allocated) { | |||
@@ -401,7 +415,9 @@ rspamd_dispatcher_write (rspamd_io_dispatcher_t *d, | |||
msg_debug ("rspamd_dispatcher_write: plan write event"); | |||
event_del (d->ev); | |||
event_set (d->ev, d->fd, EV_WRITE, dispatcher_cb, (void *)d); | |||
event_add (d->ev, d->tv); | |||
ntv = memory_pool_alloc (d->pool, sizeof (struct timeval)); | |||
memcpy (ntv, d->tv, sizeof (struct timeval)); | |||
event_add (d->ev, ntv); | |||
} | |||
} | |||
@@ -627,8 +627,9 @@ start_controller (struct rspamd_worker *worker) | |||
/* Send SIGUSR2 to parent */ | |||
kill (getppid (), SIGUSR2); | |||
gperf_profiler_init (worker->srv->cfg, "controller"); | |||
event_loop (0); | |||
exit (EXIT_SUCCESS); |
@@ -478,6 +478,7 @@ start_fuzzy_storage (struct rspamd_worker *worker) | |||
event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_fuzzy_socket, (void *)worker); | |||
event_add(&worker->bind_ev, NULL); | |||
gperf_profiler_init (worker->srv->cfg, "fuzzy"); | |||
event_loop (0); | |||
exit (EXIT_SUCCESS); |
@@ -294,6 +294,8 @@ start_lmtp_worker (struct rspamd_worker *worker) | |||
io_tv.tv_sec = WORKER_IO_TIMEOUT; | |||
io_tv.tv_usec = 0; | |||
gperf_profiler_init (worker->srv->cfg, "lmtp"); | |||
event_loop (0); | |||
exit (EXIT_SUCCESS); | |||
} |
@@ -28,9 +28,10 @@ | |||
#include "cfg_file.h" | |||
#include "main.h" | |||
#ifdef RSPAMD_MAIN | |||
sig_atomic_t do_reopen_log = 0; | |||
extern rspamd_hash_t *counters; | |||
#endif | |||
struct logger_params { | |||
GLogFunc log_func; | |||
@@ -669,7 +670,9 @@ rspamd_set_logger (GLogFunc func, struct config_file *cfg) | |||
int | |||
reopen_log (struct config_file *cfg) | |||
{ | |||
#ifdef RSPAMD_MAIN | |||
do_reopen_log = 0; | |||
#endif | |||
close_log (cfg); | |||
return open_log (cfg); | |||
} | |||
@@ -692,9 +695,11 @@ void | |||
syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) | |||
{ | |||
struct config_file *cfg = (struct config_file *)arg; | |||
#ifdef RSPAMD_MAIN | |||
if (do_reopen_log) { | |||
reopen_log (cfg); | |||
} | |||
#endif | |||
if (log_level <= cfg->log_level) { | |||
if (log_level >= G_LOG_LEVEL_DEBUG) { | |||
@@ -725,10 +730,11 @@ file_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gcha | |||
if (cfg->log_fd == -1) { | |||
return; | |||
} | |||
#ifdef RSPAMD_MAIN | |||
if (do_reopen_log) { | |||
reopen_log (cfg); | |||
} | |||
#endif | |||
if (log_level <= cfg->log_level) { | |||
now = time (NULL); | |||
@@ -844,6 +850,7 @@ calculate_check_time (struct timespec *begin, int resolution) | |||
double | |||
set_counter (const char *name, long int value) | |||
{ | |||
#ifdef RSPAMD_MAIN | |||
struct counter_data *cd; | |||
double alpha; | |||
char *key; | |||
@@ -868,6 +875,9 @@ set_counter (const char *name, long int value) | |||
} | |||
return cd->value; | |||
#else | |||
return 0; | |||
#endif | |||
} | |||
#ifndef g_tolower | |||
@@ -899,6 +909,34 @@ rspamd_strcase_hash (gconstpointer key) | |||
return h; | |||
} | |||
void | |||
gperf_profiler_init (struct config_file *cfg, const char *descr) | |||
{ | |||
#if defined(WITH_GPERF_TOOLS) && defined(MAIN_RSPAMD) | |||
char prof_path[PATH_MAX]; | |||
if (getenv("CPUPROFILE")) { | |||
/* disable inherited Profiler enabled in master process */ | |||
ProfilerStop (); | |||
} | |||
/* Try to create temp directory for gmon.out and chdir to it */ | |||
if (cfg->profile_path == NULL) { | |||
cfg->profile_path = g_strdup_printf ("%s/rspamd-profile", cfg->temp_dir); | |||
} | |||
snprintf (prof_path, sizeof (prof_path), "%s-%s.%d", cfg->profile_path, descr, (int)getpid ()); | |||
if (ProfilerStart (prof_path)) { | |||
/* start ITIMER_PROF timer */ | |||
ProfilerRegisterThread(); | |||
} | |||
else { | |||
msg_warn ("gperf_frofiler_init: cannot start google perftools profiler"); | |||
} | |||
#endif | |||
} | |||
/* | |||
* vi:ts=4 | |||
*/ |
@@ -67,5 +67,7 @@ double set_counter (const char *name, long int value); | |||
guint rspamd_strcase_hash (gconstpointer key); | |||
gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2); | |||
void gperf_profiler_init (struct config_file *cfg, const char *descr); | |||
#endif |
@@ -48,10 +48,6 @@ extern PerlInterpreter *perl_interpreter; | |||
#ifdef WITH_GPERF_TOOLS | |||
#include <glib/gprintf.h> | |||
/* Declare prototypes */ | |||
int ProfilerStart (u_char* fname); | |||
void ProfilerStop (void); | |||
void ProfilerRegisterThread (void); | |||
#endif | |||
static struct timeval io_tv; | |||
@@ -343,29 +339,7 @@ start_worker (struct rspamd_worker *worker) | |||
monstartup ((u_long) &_start, (u_long) &etext); | |||
#endif | |||
#ifdef WITH_GPERF_TOOLS | |||
char prof_path[PATH_MAX]; | |||
if (getenv("CPUPROFILE")) { | |||
/* disable inherited Profiler enabled in master process */ | |||
ProfilerStop (); | |||
} | |||
/* Try to create temp directory for gmon.out and chdir to it */ | |||
if (worker->srv->cfg->profile_path == NULL) { | |||
worker->srv->cfg->profile_path = g_strdup_printf ("%s/rspamd-profile", worker->srv->cfg->temp_dir); | |||
} | |||
snprintf (prof_path, sizeof (prof_path), "%s.%d", worker->srv->cfg->profile_path, (int)getpid ()); | |||
if (ProfilerStart (prof_path)) { | |||
/* start ITIMER_PROF timer */ | |||
ProfilerRegisterThread(); | |||
} | |||
else { | |||
msg_warn ("start_worker: cannot start google perftools profiler"); | |||
} | |||
#endif | |||
gperf_profiler_init (worker->srv->cfg, "worker"); | |||
worker->srv->pid = getpid (); | |||