* Pass to event_add only copies of struct timeval to avoid timing problemstags/0.2.7
ENDIF(ENABLE_PROFILING MATCHES "ON") | ENDIF(ENABLE_PROFILING MATCHES "ON") | ||||
IF(ENABLE_GPERF_TOOLS 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) | SET(WITH_GPERF_TOOLS 1) | ||||
ENDIF(ENABLE_GPERF_TOOLS MATCHES "ON") | ENDIF(ENABLE_GPERF_TOOLS MATCHES "ON") | ||||
${CLASSIFIERSSRC} ${PLUGINSSRC} ${YACC_OUTPUT} | ${CLASSIFIERSSRC} ${PLUGINSSRC} ${YACC_OUTPUT} | ||||
${LEX_OUTPUT}) | ${LEX_OUTPUT}) | ||||
SET_TARGET_PROPERTIES(rspamd PROPERTIES LINKER_LANGUAGE C) | 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}) | SET_TARGET_PROPERTIES(rspamd PROPERTIES VERSION ${RSPAMD_VERSION}) | ||||
IF(ENABLE_PERL MATCHES "ON") | IF(ENABLE_PERL MATCHES "ON") |
#define HAVE_SETLOCALE 1 | #define HAVE_SETLOCALE 1 | ||||
#endif | #endif | ||||
#ifdef WITH_GPERF_TOOLS | |||||
#include <google/profiler.h> | |||||
#endif | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
#include <event.h> | #include <event.h> |
GList *cur; | GList *cur; | ||||
GError *err; | GError *err; | ||||
rspamd_buffer_t *buf; | rspamd_buffer_t *buf; | ||||
struct timeval *ntv; | |||||
ssize_t r; | ssize_t r; | ||||
/* Fix order */ | /* Fix order */ | ||||
/* Wait for other event */ | /* Wait for other event */ | ||||
event_del (d->ev); | event_del (d->ev); | ||||
event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); | 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; | return; | ||||
} | } | ||||
cur = g_list_next (cur); | cur = g_list_next (cur); | ||||
event_del (d->ev); | event_del (d->ev); | ||||
event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); | 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 { | else { | ||||
/* Plan other write event */ | /* Plan other write event */ | ||||
event_del (d->ev); | event_del (d->ev); | ||||
event_set (d->ev, fd, EV_WRITE, dispatcher_cb, (void *)d); | 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); | |||||
} | } | ||||
} | } | ||||
{ | { | ||||
rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *)arg; | rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *)arg; | ||||
GError *err; | GError *err; | ||||
struct timeval *ntv; | |||||
msg_debug ("dispatcher_cb: in dispatcher callback, what: %d, fd: %d", (int)what, fd); | msg_debug ("dispatcher_cb: in dispatcher callback, what: %d, fd: %d", (int)what, fd); | ||||
if (d->out_buffers == NULL) { | if (d->out_buffers == NULL) { | ||||
event_del (d->ev); | event_del (d->ev); | ||||
event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d); | 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 { | else { | ||||
write_buffers (fd, d); | write_buffers (fd, d); | ||||
struct timeval *tv, void *user_data) | struct timeval *tv, void *user_data) | ||||
{ | { | ||||
rspamd_io_dispatcher_t *new; | rspamd_io_dispatcher_t *new; | ||||
struct timeval *ntv; | |||||
if (fd == -1) { | if (fd == -1) { | ||||
return NULL; | return NULL; | ||||
new->fd = fd; | new->fd = fd; | ||||
event_set (new->ev, fd, EV_WRITE, dispatcher_cb, (void *)new); | 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; | return new; | ||||
} | } | ||||
size_t len, gboolean delayed, gboolean allocated) | size_t len, gboolean delayed, gboolean allocated) | ||||
{ | { | ||||
rspamd_buffer_t *newbuf; | rspamd_buffer_t *newbuf; | ||||
struct timeval *ntv; | |||||
newbuf = memory_pool_alloc (d->pool, sizeof (rspamd_buffer_t)); | newbuf = memory_pool_alloc (d->pool, sizeof (rspamd_buffer_t)); | ||||
if (!allocated) { | if (!allocated) { | ||||
msg_debug ("rspamd_dispatcher_write: plan write event"); | msg_debug ("rspamd_dispatcher_write: plan write event"); | ||||
event_del (d->ev); | event_del (d->ev); | ||||
event_set (d->ev, d->fd, EV_WRITE, dispatcher_cb, (void *)d); | 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); | |||||
} | } | ||||
} | } | ||||
/* Send SIGUSR2 to parent */ | /* Send SIGUSR2 to parent */ | ||||
kill (getppid (), SIGUSR2); | kill (getppid (), SIGUSR2); | ||||
gperf_profiler_init (worker->srv->cfg, "controller"); | |||||
event_loop (0); | event_loop (0); | ||||
exit (EXIT_SUCCESS); | exit (EXIT_SUCCESS); |
event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_fuzzy_socket, (void *)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); | event_add(&worker->bind_ev, NULL); | ||||
gperf_profiler_init (worker->srv->cfg, "fuzzy"); | |||||
event_loop (0); | event_loop (0); | ||||
exit (EXIT_SUCCESS); | exit (EXIT_SUCCESS); |
io_tv.tv_sec = WORKER_IO_TIMEOUT; | io_tv.tv_sec = WORKER_IO_TIMEOUT; | ||||
io_tv.tv_usec = 0; | io_tv.tv_usec = 0; | ||||
gperf_profiler_init (worker->srv->cfg, "lmtp"); | |||||
event_loop (0); | event_loop (0); | ||||
exit (EXIT_SUCCESS); | exit (EXIT_SUCCESS); | ||||
} | } |
#include "cfg_file.h" | #include "cfg_file.h" | ||||
#include "main.h" | #include "main.h" | ||||
#ifdef RSPAMD_MAIN | |||||
sig_atomic_t do_reopen_log = 0; | sig_atomic_t do_reopen_log = 0; | ||||
extern rspamd_hash_t *counters; | extern rspamd_hash_t *counters; | ||||
#endif | |||||
struct logger_params { | struct logger_params { | ||||
GLogFunc log_func; | GLogFunc log_func; | ||||
int | int | ||||
reopen_log (struct config_file *cfg) | reopen_log (struct config_file *cfg) | ||||
{ | { | ||||
#ifdef RSPAMD_MAIN | |||||
do_reopen_log = 0; | do_reopen_log = 0; | ||||
#endif | |||||
close_log (cfg); | close_log (cfg); | ||||
return open_log (cfg); | return open_log (cfg); | ||||
} | } | ||||
syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) | syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) | ||||
{ | { | ||||
struct config_file *cfg = (struct config_file *)arg; | struct config_file *cfg = (struct config_file *)arg; | ||||
#ifdef RSPAMD_MAIN | |||||
if (do_reopen_log) { | if (do_reopen_log) { | ||||
reopen_log (cfg); | reopen_log (cfg); | ||||
} | } | ||||
#endif | |||||
if (log_level <= cfg->log_level) { | if (log_level <= cfg->log_level) { | ||||
if (log_level >= G_LOG_LEVEL_DEBUG) { | if (log_level >= G_LOG_LEVEL_DEBUG) { | ||||
if (cfg->log_fd == -1) { | if (cfg->log_fd == -1) { | ||||
return; | return; | ||||
} | } | ||||
#ifdef RSPAMD_MAIN | |||||
if (do_reopen_log) { | if (do_reopen_log) { | ||||
reopen_log (cfg); | reopen_log (cfg); | ||||
} | } | ||||
#endif | |||||
if (log_level <= cfg->log_level) { | if (log_level <= cfg->log_level) { | ||||
now = time (NULL); | now = time (NULL); | ||||
double | double | ||||
set_counter (const char *name, long int value) | set_counter (const char *name, long int value) | ||||
{ | { | ||||
#ifdef RSPAMD_MAIN | |||||
struct counter_data *cd; | struct counter_data *cd; | ||||
double alpha; | double alpha; | ||||
char *key; | char *key; | ||||
} | } | ||||
return cd->value; | return cd->value; | ||||
#else | |||||
return 0; | |||||
#endif | |||||
} | } | ||||
#ifndef g_tolower | #ifndef g_tolower | ||||
return h; | 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 | * vi:ts=4 | ||||
*/ | */ |
guint rspamd_strcase_hash (gconstpointer key); | guint rspamd_strcase_hash (gconstpointer key); | ||||
gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2); | gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2); | ||||
void gperf_profiler_init (struct config_file *cfg, const char *descr); | |||||
#endif | #endif |
#ifdef WITH_GPERF_TOOLS | #ifdef WITH_GPERF_TOOLS | ||||
#include <glib/gprintf.h> | #include <glib/gprintf.h> | ||||
/* Declare prototypes */ | |||||
int ProfilerStart (u_char* fname); | |||||
void ProfilerStop (void); | |||||
void ProfilerRegisterThread (void); | |||||
#endif | #endif | ||||
static struct timeval io_tv; | static struct timeval io_tv; | ||||
monstartup ((u_long) &_start, (u_long) &etext); | monstartup ((u_long) &_start, (u_long) &etext); | ||||
#endif | #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 (); | worker->srv->pid = getpid (); | ||||