[core] split cond cache from cond matches

personal/stbuehler/ci-build
Glenn Strauss 2019-11-21 00:15:51 -05:00
parent 5977ce2b4a
commit c193da3404
9 changed files with 85 additions and 74 deletions

View File

@ -16,6 +16,8 @@
struct fdevents; /* declaration */
struct stat_cache; /* declaration */
struct cond_cache_t; /* declaration */
struct cond_match_t; /* declaration */
#define DIRECT 0 /* con->mode */
@ -147,32 +149,6 @@ typedef enum {
CON_STATE_CLOSE
} connection_state_t;
typedef enum {
/* condition not active at the moment because itself or some
* pre-condition depends on data not available yet
*/
COND_RESULT_UNSET,
/* special "unset" for branches not selected due to pre-conditions
* not met (but pre-conditions are not "unset" anymore)
*/
COND_RESULT_SKIP,
/* actually evaluated the condition itself */
COND_RESULT_FALSE, /* not active */
COND_RESULT_TRUE /* active */
} cond_result_t;
typedef struct cond_cache_t {
/* current result (with preconditions) */
cond_result_t result;
/* result without preconditions (must never be "skip") */
cond_result_t local_result;
const buffer *comp_value; /* just a pointer */
int patterncount;
int matches[3 * 10];
} cond_cache_t;
struct connection {
connection_state_t state;
@ -242,7 +218,8 @@ struct connection {
specific_config conf; /* global connection specific config */
uint32_t conditional_is_valid;
cond_cache_t *cond_cache;
struct cond_cache_t *cond_cache;
struct cond_match_t *cond_match;
const buffer *server_name;
buffer *proto;

View File

@ -351,7 +351,7 @@ static int config_addrbuf_eq_remote_ip_mask(connection *con, const buffer *strin
return config_addrstr_eq_remote_ip_mask(con, addrstr, nm_bits, rmt);
}
static int data_config_pcre_exec(const data_config *dc, cond_cache_t *cache, const buffer *b);
static int data_config_pcre_exec(const data_config *dc, cond_cache_t *cache, const buffer *b, cond_match_t *cond_match);
static cond_result_t config_check_cond_nocache(connection *con, const data_config *dc, const int debug_cond, cond_cache_t * const cache) {
static struct const_char_buffer {
@ -544,7 +544,8 @@ static cond_result_t config_check_cond_nocache(connection *con, const data_confi
}
case CONFIG_COND_NOMATCH:
case CONFIG_COND_MATCH: {
if (data_config_pcre_exec(dc, cache, l) > 0) {
cond_match_t *cond_match = con->cond_match + dc->context_ndx;
if (data_config_pcre_exec(dc, cache, l, cond_match) > 0) {
return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
} else {
/* cache is already cleared */
@ -576,38 +577,25 @@ int config_check_cond(connection * const con, const int context_ndx) {
cond_cache_t * const cache = &con->cond_cache[context_ndx];
return COND_RESULT_TRUE
== (COND_RESULT_UNSET != cache->result
? cache->result
? (cond_result_t)cache->result
: config_check_cond_calc(con, context_ndx, cache));
}
/* if we reset the cache result for a node, we also need to clear all
* child nodes and else-branches*/
static void config_cond_clear_node(server *srv, connection *con, const data_config *dc) {
static void config_cond_clear_node(cond_cache_t * const cond_cache, const data_config * const dc) {
/* if a node is "unset" all children are unset too */
if (con->cond_cache[dc->context_ndx].result != COND_RESULT_UNSET) {
size_t i;
if (cond_cache[dc->context_ndx].result != COND_RESULT_UNSET) {
cond_cache[dc->context_ndx].result = COND_RESULT_UNSET;
#if 0
/* (redundant; matches not relevant unless COND_RESULT_TRUE) */
switch (con->cond_cache[dc->context_ndx].local_result) {
case COND_RESULT_TRUE:
case COND_RESULT_FALSE:
break;
default:
con->cond_cache[dc->context_ndx].patterncount = 0;
con->cond_cache[dc->context_ndx].comp_value = NULL;
}
#endif
con->cond_cache[dc->context_ndx].result = COND_RESULT_UNSET;
for (i = 0; i < dc->children.used; ++i) {
for (uint32_t i = 0; i < dc->children.used; ++i) {
const data_config *dc_child = dc->children.data[i];
if (NULL == dc_child->prev) {
/* only call for first node in if-else chain */
config_cond_clear_node(srv, con, dc_child);
config_cond_clear_node(cond_cache, dc_child);
}
}
if (NULL != dc->next) config_cond_clear_node(srv, con, dc->next);
if (NULL != dc->next) config_cond_clear_node(cond_cache, dc->next);
}
}
@ -617,14 +605,15 @@ static void config_cond_clear_node(server *srv, connection *con, const data_conf
* if the item is COND_LAST_ELEMENT we reset all items
*/
void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item) {
cond_cache_t * const cond_cache = con->cond_cache;
for (uint32_t i = 0; i < srv->config_context->used; ++i) {
const data_config *dc = (data_config *)srv->config_context->data[i];
if (item == dc->comp) {
/* clear local_result */
con->cond_cache[i].local_result = COND_RESULT_UNSET;
cond_cache[i].local_result = COND_RESULT_UNSET;
/* clear result in subtree (including the node itself) */
config_cond_clear_node(srv, con, dc);
config_cond_clear_node(cond_cache, dc);
}
}
}
@ -633,36 +622,34 @@ void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item)
* reset the config cache to its initial state at connection start
*/
void config_cond_cache_reset(server *srv, connection *con) {
cond_cache_t * const cond_cache = con->cond_cache;
con->conditional_is_valid = 0;
/* resetting all entries; no need to follow children as in config_cond_cache_reset_item */
for (uint32_t i = 1, used = srv->config_context->used; i < used; ++i) {
cond_cache[i].result = COND_RESULT_UNSET;
cond_cache[i].local_result = COND_RESULT_UNSET;
cond_cache[i].patterncount = 0;
cond_cache[i].comp_value = NULL;
}
/* static_assert(0 == COND_RESULT_UNSET); */
const uint32_t used = srv->config_context->used;
if (used > 1)
memset(con->cond_cache, 0, used*sizeof(cond_cache_t));
}
#ifdef HAVE_PCRE_H
#include <pcre.h>
#endif
static int data_config_pcre_exec(const data_config *dc, cond_cache_t *cache, const buffer *b) {
static int data_config_pcre_exec(const data_config *dc, cond_cache_t *cache, const buffer *b, cond_match_t *cond_match) {
#ifdef HAVE_PCRE_H
#ifndef elementsof
#define elementsof(x) (sizeof(x) / sizeof(x[0]))
#endif
cache->patterncount =
pcre_exec(dc->regex, dc->regex_study, CONST_BUF_LEN(b), 0, 0,
cache->matches, elementsof(cache->matches));
cond_match->matches, elementsof(cond_match->matches));
if (cache->patterncount > 0)
cache->comp_value = b; /* holds pointer to b (!) for pattern subst */
cond_match->comp_value = b; /*holds pointer to b (!) for pattern subst*/
return cache->patterncount;
#else
UNUSED(dc);
UNUSED(cache);
UNUSED(b);
UNUSED(cond_match);
return 0;
#endif
}

View File

@ -587,6 +587,12 @@ static connection *connection_init(server *srv) {
con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
force_assert(NULL != con->cond_cache);
#ifdef HAVE_PCRE_H
if (srv->config_context->used > 1) {/*save 128b per con if no conditions)*/
con->cond_match=calloc(srv->config_context->used, sizeof(cond_match_t));
force_assert(NULL != con->cond_match);
}
#endif
config_reset_config(srv, con);
return con;
@ -633,6 +639,7 @@ void connections_free(server *srv) {
#undef CLEAN
free(con->plugin_ctx);
free(con->cond_cache);
free(con->cond_match);
free(con);
}

View File

@ -1,7 +1,7 @@
#include "first.h"
#include "keyvalue.h"
#include "base.h" /* struct cond_cache_t */
#include "plugin_config.h" /* struct cond_match_t */
#include "burl.h"
#include "log.h"
@ -95,9 +95,9 @@ static void pcre_keyvalue_buffer_append_match(buffer *b, const char **list, int
}
static void pcre_keyvalue_buffer_append_ctxmatch(buffer *b, pcre_keyvalue_ctx *ctx, unsigned int num, int flags) {
const struct cond_cache_t * const cache = ctx->cache;
const struct cond_match_t * const cache = ctx->cache;
if (!cache) return; /* no enclosing match context */
if ((int)num < cache->patterncount) {
if ((int)num < ctx->cond_match_count) {
const int off = cache->matches[(num <<= 1)]; /*(num *= 2)*/
const int len = cache->matches[num+1] - off;
burl_append(b, cache->comp_value->ptr + off, (size_t)len, flags);

View File

@ -6,12 +6,13 @@
#include "buffer.h"
struct burl_parts_t; /* declaration */
struct cond_cache_t; /* declaration */
struct cond_match_t; /* declaration */
struct pcre_keyvalue; /* declaration */
typedef struct pcre_keyvalue_ctx {
struct cond_cache_t *cache;
struct cond_match_t *cache;
struct burl_parts_t *burl;
int cond_match_count;
int m;
} pcre_keyvalue_ctx;

View File

@ -159,9 +159,12 @@ URIHANDLER_FUNC(mod_redirect_uri_handler) {
mod_redirect_patch_config(con, p);
if (!p->conf.redirect || !p->conf.redirect->used) return HANDLER_GO_ON;
ctx.cache = p->conf.redirect->x0
? &con->cond_cache[p->conf.redirect->x0]
: NULL;
ctx.cache = NULL;
if (p->conf.redirect->x0) { /*(p->conf.redirect->x0 is context_idx)*/
ctx.cond_match_count=con->cond_cache[p->conf.redirect->x0].patterncount;
ctx.cache = con->cond_match + p->conf.redirect->x0;
}
ctx.burl = &burl;
burl.scheme = con->uri.scheme;
burl.authority = con->uri.authority;

View File

@ -287,8 +287,11 @@ static handler_t process_rewrite_rules(server *srv, connection *con, plugin_data
if (*hctx & REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
}
/*(kvb->x0 is context_idx)*/
ctx.cache = kvb->x0 ? &con->cond_cache[kvb->x0] : NULL;
ctx.cache = NULL;
if (kvb->x0) { /*(kvb->x0 is context_idx)*/
ctx.cond_match_count = con->cond_cache[kvb->x0].patterncount;
ctx.cache = con->cond_match + kvb->x0;
}
ctx.burl = &burl;
burl.scheme = con->uri.scheme;
burl.authority = con->uri.authority;

View File

@ -123,6 +123,38 @@ int config_plugin_values_init_block(server * const srv, const array * const ca,
__attribute_cold__
int config_plugin_values_init(server *srv, void *p_d, const config_plugin_keys_t *cpk, const char *mname);
typedef enum {
/* condition not active at the moment because itself or some
* pre-condition depends on data not available yet
*/
COND_RESULT_UNSET,
/* special "unset" for branches not selected due to pre-conditions
* not met (but pre-conditions are not "unset" anymore)
*/
COND_RESULT_SKIP,
/* actually evaluated the condition itself */
COND_RESULT_FALSE, /* not active */
COND_RESULT_TRUE /* active */
} cond_result_t;
typedef struct cond_cache_t {
/* current result (with preconditions) */
int8_t result; /*(cond_result_t)*/
/* result without preconditions (must never be "skip") */
int8_t local_result; /*(cond_result_t)*/
int16_t patterncount;
} cond_cache_t; /* 8 bytes (2^3) */
typedef struct cond_match_t {
const buffer *comp_value; /* just a pointer */
#if !(defined(_LP64) || defined(__LP64__) || defined(_WIN64)) /*(not 64-bit)*/
int dummy_alignment; /*(for alignment in 32-bit)*/
#endif
int matches[3 * 10];
} cond_match_t; /* 128 bytes (2^7) */
int config_check_cond(connection *con, int context_ndx);
#endif

View File

@ -8,7 +8,8 @@
#include "keyvalue.c"
#include "base.h" /* struct server, struct cond_cache_t */
#include "base.h" /* struct server */
#include "plugin_config.h" /* struct cond_match_t */
#ifdef HAVE_PCRE_H
static pcre_keyvalue_buffer * test_keyvalue_test_kvb_init (void) {
@ -47,7 +48,7 @@ static void test_keyvalue_pcre_keyvalue_buffer_process (void) {
buffer *url = buffer_init();
buffer *result = buffer_init();
struct burl_parts_t burl;
cond_cache_t cache;
cond_match_t cache;
pcre_keyvalue_ctx ctx;
handler_t rc;
buffer *scheme = buffer_init();
@ -64,9 +65,9 @@ static void test_keyvalue_pcre_keyvalue_buffer_process (void) {
buffer_copy_string_len(scheme, CONST_STR_LEN("http"));
buffer_copy_string_len(authority, CONST_STR_LEN("www.example.com"));
/* model outer conditional match of $HTTP["host"] =~ "^(www).example.com$" */
ctx.cond_match_count = 2;
ctx.cache = &cache;
memset(&cache, 0, sizeof(cache));
cache.patterncount = 2;
cache.comp_value = authority;
cache.matches[0] = 0;
cache.matches[1] = 15;