}
if ((ncompiled = rspamd_re_cache_compile_hyperscan (ctx->cfg->re_cache,
- ctx->hs_dir, ctx->max_time,
+ ctx->hs_dir, ctx->max_time, !forced,
&err)) == -1) {
msg_err ("failed to compile re cache: %e", err);
g_error_free (err);
return FALSE;
}
- msg_info ("compiled %d regular expressions to the hyperscan tree",
- ncompiled);
+ if (ncompiled > 0) {
+ msg_info ("compiled %d regular expressions to the hyperscan tree",
+ ncompiled);
+ forced = TRUE;
+ }
/*
* Do not send notification unless all other workers are started
srv_cmd.type = RSPAMD_SRV_HYPERSCAN_LOADED;
srv_cmd.cmd.hs_loaded.cache_dir = ctx->hs_dir;
+ srv_cmd.cmd.hs_loaded.forced = forced;
rspamd_srv_send_command (worker, ctx->ev_base, &srv_cmd, NULL, NULL);
guint max_re_data;
gchar hash[rspamd_cryptobox_HASHBYTES + 1];
#ifdef WITH_HYPERSCAN
+ gboolean hyperscan_loaded;
gboolean disable_hyperscan;
hs_platform_info_t plt;
#endif
cache->re_classes = g_hash_table_new (g_int64_hash, g_int64_equal);
cache->nre = 0;
cache->re = g_ptr_array_new_full (256, rspamd_re_cache_elt_dtor);
+#ifdef WITH_HYPERSCAN
+ cache->hyperscan_loaded = FALSE;
+#endif
REF_INIT_RETAIN (cache, rspamd_re_cache_destroy);
return cache;
}
+gboolean
+rspamd_re_cache_is_hs_loaded (struct rspamd_re_cache *cache)
+{
+ g_assert (cache != NULL);
+
+#ifdef WITH_HYPERSCAN
+ return cache->hyperscan_loaded;
+#else
+ return FALSE;
+#endif
+}
+
rspamd_regexp_t *
rspamd_re_cache_add (struct rspamd_re_cache *cache, rspamd_regexp_t *re,
enum rspamd_re_type type, gpointer type_data, gsize datalen)
gint
rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache,
- const char *cache_dir, gdouble max_time,
+ const char *cache_dir, gdouble max_time, gboolean silent,
GError **err)
{
g_assert (cache != NULL);
g_assert (fd != -1);
lseek (fd, RSPAMD_HS_MAGIC_LEN + sizeof (cache->plt), SEEK_SET);
read (fd, &n, sizeof (n));
- total += n;
close (fd);
if (re_class->type_len > 0) {
- msg_info_re_cache (
- "skip already valid class %s(%*s) to cache %6s, %d regexps",
- rspamd_re_cache_type_to_string (re_class->type),
- (gint) re_class->type_len - 1,
- re_class->type_data,
- re_class->hash,
- n);
+ if (!silent) {
+ msg_info_re_cache (
+ "skip already valid class %s(%*s) to cache %6s, %d regexps",
+ rspamd_re_cache_type_to_string (re_class->type),
+ (gint) re_class->type_len - 1,
+ re_class->type_data,
+ re_class->hash,
+ n);
+ }
}
else {
- msg_info_re_cache (
- "skip already valid class %s to cache %6s, %d regexps",
- rspamd_re_cache_type_to_string (re_class->type),
- re_class->hash,
- n);
+ if (!silent) {
+ msg_info_re_cache (
+ "skip already valid class %s to cache %6s, %d regexps",
+ rspamd_re_cache_type_to_string (re_class->type),
+ re_class->hash,
+ n);
+ }
}
continue;
}
msg_info_re_cache ("hyperscan database of %d regexps has been loaded", total);
+ cache->hyperscan_loaded = TRUE;
return TRUE;
#endif
void rspamd_re_cache_init (struct rspamd_re_cache *cache,
struct rspamd_config *cfg);
+/**
+ * Returns true when hyperscan is loaded
+ * @param cache
+ * @return
+ */
+gboolean rspamd_re_cache_is_hs_loaded (struct rspamd_re_cache *cache);
+
/**
* Get runtime data for a cache
*/
* Compile expressions to the hyperscan tree and store in the `cache_dir`
*/
gint rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache,
- const char *cache_dir, gdouble max_time,
+ const char *cache_dir, gdouble max_time, gboolean silent,
GError **err);
* workers
*/
wcmd.cmd.hs_loaded.cache_dir = cmd.cmd.hs_loaded.cache_dir;
+ wcmd.cmd.hs_loaded.forced = cmd.cmd.hs_loaded.forced;
rspamd_control_broadcast_cmd (srv, &wcmd,
rspamd_control_hs_io_handler, NULL);
- rdata->rep.reply.hs_loaded.unused = 0;
break;
default:
msg_err ("unknown command type: %d", cmd.type);
} recompile;
struct {
gpointer cache_dir;
+ gboolean forced;
} hs_loaded;
struct {
guint unused;
} spair;
struct {
gpointer cache_dir;
+ gboolean forced;
} hs_loaded;
} cmd;
};
gint code;
} spair;
struct {
- gint unused;
+ gint forced;
} hs_loaded;
} reply;
};
gpointer ud)
{
struct rspamd_control_reply rep;
+ struct rspamd_re_cache *cache = worker->srv->cfg->re_cache;
- msg_info ("loading hyperscan expressions after receiving compilation notice");
memset (&rep, 0, sizeof (rep));
rep.type = RSPAMD_CONTROL_HYPERSCAN_LOADED;
- rep.reply.hs_loaded.status = rspamd_re_cache_load_hyperscan (
- worker->srv->cfg->re_cache, cmd->cmd.hs_loaded.cache_dir);
+ if (!rspamd_re_cache_is_hs_loaded (cache) || cmd->cmd.hs_loaded.forced) {
+ msg_info ("loading hyperscan expressions after receiving compilation "
+ "notice: %s",
+ (!rspamd_re_cache_is_hs_loaded (cache)) ?
+ "new db" : "forced update");
+ rep.reply.hs_loaded.status = rspamd_re_cache_load_hyperscan (
+ worker->srv->cfg->re_cache, cmd->cmd.hs_loaded.cache_dir);
+ }
if (write (fd, &rep, sizeof (rep)) != sizeof (rep)) {
msg_err ("cannot write reply to the control socket: %s",