g_hash_table_insert (re_cache, line, pointer);
}
+/* Task cache functions */
+void
+task_cache_add (struct worker_task *task, void *pointer, int32_t result)
+{
+ g_hash_table_insert (task->re_cache, pointer, GINT_TO_POINTER (result));
+}
+
+int32_t
+task_cache_check (struct worker_task *task, void *pointer)
+{
+ gpointer res;
+ if ((res = g_hash_table_lookup (task->re_cache, pointer)) != NULL) {
+ return GPOINTER_TO_INT (res);
+ }
+ return -1;
+}
+
/*
* Functions for parsing expressions
*/
struct expression_argument *arg;
GMimeObject *part;
const GMimeContentType *ct;
+ int r;
if (args == NULL) {
msg_warn ("rspamd_content_type_compare_param: no parameters to function");
}
re_cache_add (param_pattern, re);
}
- if (g_regex_match (re->regexp, param_data, 0, NULL) == TRUE) {
- return TRUE;
+ if ((r = task_cache_check (task, re)) == -1) {
+ if (g_regex_match (re->regexp, param_data, 0, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
+ return TRUE;
+ }
+ task_cache_add (task, re, 0);
+ }
+ else {
+ return r == 1;
}
}
else {
struct expression_argument *arg;
GMimeObject *part;
const localContentType *ct;
+ int r;
if (args == NULL) {
msg_warn ("rspamd_content_type_compare_param: no parameters to function");
}
re_cache_add (param_pattern, re);
}
- if (g_regex_match (re->regexp, ct->subtype, 0, NULL) == TRUE) {
- return TRUE;
+ if ((r = task_cache_check (task, re)) == -1) {
+ if (g_regex_match (re->regexp, ct->subtype, 0, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
+ return TRUE;
+ }
+ task_cache_add (task, re, 0);
+ }
+ else {
+ return r == 1;
}
}
else {
GMimeObject *part;
const localContentType *ct;
struct expression_argument *arg;
+ int r;
if (args == NULL) {
msg_warn ("rspamd_content_type_compare_param: no parameters to function");
}
re_cache_add (param_pattern, re);
}
- if (g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) {
- return TRUE;
+ if ((r = task_cache_check (task, re)) == -1) {
+ if (g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
+ return TRUE;
+ }
+ task_cache_add (task, re, 0);
+ }
+ else {
+ return r == 1;
}
}
else {
compare_subtype (struct worker_task *task, const localContentType *ct, char *subtype)
{
struct rspamd_regexp *re;
+ int r;
if (*subtype == '/') {
/* This is regexp, so compile and create g_regexp object */
}
re_cache_add (subtype, re);
}
- if (g_regex_match (re->regexp, ct->subtype , 0, NULL) == TRUE) {
- return TRUE;
+ if ((r = task_cache_check (task, re)) == -1) {
+ if (g_regex_match (re->regexp, subtype, 0, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
+ return TRUE;
+ }
+ task_cache_add (task, re, 0);
+ }
+ else {
+ return r == 1;
}
}
else {
struct mime_part *part;
GList *cur;
const localContentType *ct;
-
+ int r;
cur = g_list_first (task->parts);
while (cur) {
}
re_cache_add (param_type, re);
}
- if (g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) {
- if (param_subtype) {
- if (compare_subtype (task, ct, param_subtype)) {
+ if ((r = task_cache_check (task, re)) == -1) {
+ if (g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) {
+ if (param_subtype) {
+ if (compare_subtype (task, ct, param_subtype)) {
+ if (compare_len (part, min_len, max_len)) {
+ return TRUE;
+ }
+ }
+ }
+ else {
if (compare_len (part, min_len, max_len)) {
return TRUE;
}
}
+ task_cache_add (task, re, 1);
}
else {
- if (compare_len (part, min_len, max_len)) {
- return TRUE;
+ task_cache_add (task, re, 0);
+ }
+ }
+ else {
+ if (r == 1) {
+ if (compare_subtype (task, ct, param_subtype)) {
+ if (compare_len (part, min_len, max_len)) {
+ return TRUE;
+ }
}
}
}
*/
void * re_cache_check (const char *line);
+/**
+ * Add regexp to regexp task cache
+ * @param task task object
+ * @param pointer regexp data
+ * @param result numeric result of this regexp
+ */
+void task_cache_add (struct worker_task *task, void *pointer, int32_t result);
+
+/**
+ * Check regexp in cache
+ * @param task task object
+ * @param pointer regexp data
+ * @return numeric result if value exists or -1 if not
+ */
+int32_t task_cache_check (struct worker_task *task, void *pointer);
+
#endif
TAILQ_HEAD (uriq, uri) urls; /**< list of parsed urls */
GHashTable *results; /**< hash table of metric_result indexed by
* metric's name */
+ GHashTable *re_cache; /**< cache for matched or not matched regexps */
struct config_file *cfg; /**< pointer to config object */
struct save_point save; /**< save point for delayed processing */
char *last_error; /**< last error */
struct mime_text_part *part;
GList *cur, *headerlist;
struct uri *url;
+ int r;
if (re == NULL) {
msg_info ("process_regexp: invalid regexp passed");
return 0;
}
+
+ if ((r = task_cache_check (task, re)) != -1) {
+ return r == 1;
+ }
switch (re->type) {
case REGEXP_NONE:
case REGEXP_HEADER:
if (re->header == NULL) {
msg_info ("process_regexp: header regexp without header name");
+ task_cache_add (task, re, 0);
return 0;
}
msg_debug ("process_regexp: checking header regexp: %s = /%s/", re->header, re->regexp_text);
headerlist = message_get_header (task->task_pool, task->message, re->header);
if (headerlist == NULL) {
+ task_cache_add (task, re, 0);
return 0;
}
else {
if (re->regexp == NULL) {
msg_debug ("process_regexp: regexp contains only header and it is found %s", re->header);
+ task_cache_add (task, re, 1);
g_list_free (headerlist);
return 1;
}
cur = headerlist;
while (cur) {
if (cur->data && g_regex_match (re->regexp, cur->data, 0, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
return 1;
}
cur = g_list_next (cur);
}
g_list_free (headerlist);
+ task_cache_add (task, re, 0);
return 0;
}
break;
while (cur) {
part = (struct mime_text_part *)cur->data;
if (g_regex_match_full (re->regexp, part->orig->data, part->orig->len, 0, 0, NULL, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
return 1;
}
cur = g_list_next (cur);
}
+ task_cache_add (task, re, 0);
return 0;
case REGEXP_MESSAGE:
msg_debug ("process_regexp: checking message regexp: /%s/", re->regexp_text);
if (g_regex_match_full (re->regexp, task->msg->begin, task->msg->len, 0, 0, NULL, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
return 1;
}
+ task_cache_add (task, re, 0);
return 0;
case REGEXP_URL:
msg_debug ("process_regexp: checking url regexp: /%s/", re->regexp_text);
TAILQ_FOREACH (url, &task->urls, next) {
if (g_regex_match (re->regexp, struri (url), 0, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
return 1;
}
}
+ task_cache_add (task, re, 0);
return 0;
case REGEXP_RAW_HEADER:
msg_debug ("process_regexp: checking for raw header: %s with regexp: /%s/", re->header, re->regexp_text);
if (task->raw_headers == NULL) {
msg_debug ("process_regexp: cannot check for raw header in message, no headers found");
+ task_cache_add (task, re, 0);
return 0;
}
if ((headerv = strstr (task->raw_headers, re->header)) == NULL) {
/* No header was found */
+ task_cache_add (task, re, 0);
return 0;
}
/* Skip header name and start matching after regexp */
*c = '\0';
if (g_regex_match (re->regexp, headerv, 0, NULL) == TRUE) {
*c = t;
+ task_cache_add (task, re, 1);
return 1;
}
*c = t;
+ task_cache_add (task, re, 0);
return 0;
}
memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func)rcpt_destruct, new_task);
new_task->results = g_hash_table_new (g_str_hash, g_str_equal);
memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func)g_hash_table_destroy, new_task->results);
+ new_task->re_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func)g_hash_table_destroy, new_task->re_cache);
worker->srv->stat->connections_count ++;