From 8b52bb387809aab73d518940a717189ddc0b6feb Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Fri, 16 Nov 2012 18:06:41 +0100 Subject: [PATCH] MEDIUM: compression: use pool for comp_ctx Use pool for comp_ctx, it is allocated during the comp_algo->init(). The allocation of comp_ctx is accounted for in the zlib_memory_available. --- include/proto/compression.h | 11 ++-- include/types/compression.h | 4 +- include/types/session.h | 2 +- src/cfgparse.c | 2 +- src/compression.c | 123 +++++++++++++++++++++++++++--------- src/proto_http.c | 2 - 6 files changed, 101 insertions(+), 43 deletions(-) diff --git a/include/proto/compression.h b/include/proto/compression.h index cfab62a075..1614eddfcd 100644 --- a/include/proto/compression.h +++ b/include/proto/compression.h @@ -33,22 +33,21 @@ int http_compression_buffer_init(struct session *s, struct buffer *in, struct bu int http_compression_buffer_add_data(struct session *s, struct buffer *in, struct buffer *out); int http_compression_buffer_end(struct session *s, struct buffer **in, struct buffer **out, int end); -int identity_init(struct comp_ctx *comp_ctx, int level); +int identity_init(struct comp_ctx **comp_ctx, int level); int identity_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out); int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out, int flag); int identity_reset(struct comp_ctx *comp_ctx); -int identity_end(struct comp_ctx *comp_ctx); +int identity_end(struct comp_ctx **comp_ctx); #ifdef USE_ZLIB - -int deflate_init(struct comp_ctx *comp_ctx, int level); +int deflate_init(struct comp_ctx **comp_ctx, int level); int deflate_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out); int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out, int flag); int deflate_reset(struct comp_ctx *comp_ctx); -int deflate_end(struct comp_ctx *comp_ctx); +int deflate_end(struct comp_ctx **comp_ctx); -int gzip_init(struct comp_ctx *comp_ctx, int level); +int gzip_init(struct comp_ctx **comp_ctx, int level); #endif /* USE_ZLIB */ #endif /* _PROTO_COMP_H */ diff --git a/include/types/compression.h b/include/types/compression.h index cf56e457b3..e4b1f273d3 100644 --- a/include/types/compression.h +++ b/include/types/compression.h @@ -50,11 +50,11 @@ struct comp_ctx { struct comp_algo { char *name; int name_len; - int (*init)(struct comp_ctx *comp_ctx, int level); + int (*init)(struct comp_ctx **comp_ctx, int level); int (*add_data)(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out); int (*flush)(struct comp_ctx *comp_ctx, struct buffer *out, int flag); int (*reset)(struct comp_ctx *comp_ctx); - int (*end)(struct comp_ctx *comp_ctx); + int (*end)(struct comp_ctx **comp_ctx); struct comp_algo *next; }; diff --git a/include/types/session.h b/include/types/session.h index 284b7e892b..e0d3c2274f 100644 --- a/include/types/session.h +++ b/include/types/session.h @@ -159,7 +159,7 @@ struct session { void (*srv_error)(struct session *s, /* the function to call upon unrecoverable server errors (or NULL) */ struct stream_interface *si); unsigned int uniq_id; /* unique ID used for the traces */ - struct comp_ctx comp_ctx; /* HTTP compression context */ + struct comp_ctx *comp_ctx; /* HTTP compression context */ struct comp_algo *comp_algo; /* HTTP compression algorithm if not NULL */ char *unique_id; /* custom unique ID */ }; diff --git a/src/cfgparse.c b/src/cfgparse.c index 10fc4a644b..d4b3d9182b 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -5442,7 +5442,7 @@ stats_error_parsing: if (!strcmp(args[1], "algo")) { int cur_arg; - struct comp_ctx ctx; + struct comp_ctx *ctx; cur_arg = 2; if (!*args[cur_arg]) { diff --git a/src/compression.c b/src/compression.c index 72c9996b93..c1e1afd795 100644 --- a/src/compression.c +++ b/src/compression.c @@ -37,6 +37,9 @@ #ifdef USE_ZLIB +static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size); +static void free_zlib(void *opaque, void *ptr); + /* zlib allocation */ static struct pool_head *zlib_pool_deflate_state = NULL; static struct pool_head *zlib_pool_window = NULL; @@ -46,9 +49,10 @@ static struct pool_head *zlib_pool_pending_buf = NULL; static long long zlib_memory_available = -1; - #endif +static struct pool_head *pool_comp_ctx = NULL; + const struct comp_algo comp_algos[] = { @@ -187,15 +191,15 @@ int http_compression_buffer_add_data(struct session *s, struct buffer *in, struc left = data_process_len - bi_contig_data(in); if (left <= 0) { - consumed_data += ret = s->comp_algo->add_data(&s->comp_ctx, bi_ptr(in), data_process_len, out); + consumed_data += ret = s->comp_algo->add_data(s->comp_ctx, bi_ptr(in), data_process_len, out); if (ret < 0) return -1; } else { - consumed_data += ret = s->comp_algo->add_data(&s->comp_ctx, bi_ptr(in), bi_contig_data(in), out); + consumed_data += ret = s->comp_algo->add_data(s->comp_ctx, bi_ptr(in), bi_contig_data(in), out); if (ret < 0) return -1; - consumed_data += ret = s->comp_algo->add_data(&s->comp_ctx, in->data, left, out); + consumed_data += ret = s->comp_algo->add_data(s->comp_ctx, in->data, left, out); if (ret < 0) return -1; } @@ -223,9 +227,9 @@ int http_compression_buffer_end(struct session *s, struct buffer **in, struct bu /* flush data here */ if (end) - ret = s->comp_algo->flush(&s->comp_ctx, ob, Z_FINISH); /* end of data */ + ret = s->comp_algo->flush(s->comp_ctx, ob, Z_FINISH); /* end of data */ else - ret = s->comp_algo->flush(&s->comp_ctx, ob, Z_SYNC_FLUSH); /* end of buffer */ + ret = s->comp_algo->flush(s->comp_ctx, ob, Z_SYNC_FLUSH); /* end of buffer */ if (ret < 0) return -1; /* flush failed */ @@ -257,9 +261,8 @@ int http_compression_buffer_end(struct session *s, struct buffer **in, struct bu } to_forward = ob->i; - /* update input rate */ - if (s->comp_ctx.cur_lvl > 0) + if (s->comp_ctx && s->comp_ctx->cur_lvl > 0) update_freq_ctr(&global.comp_bps_in, ib->o - ob->o); /* copy the remaining data in the tmp buffer. */ @@ -277,7 +280,7 @@ int http_compression_buffer_end(struct session *s, struct buffer **in, struct bu *in = ob; *out = ib; - if (s->comp_ctx.cur_lvl > 0) + if (s->comp_ctx && s->comp_ctx->cur_lvl > 0) update_freq_ctr(&global.comp_bps_out, to_forward); /* forward the new chunk without remaining data */ @@ -290,6 +293,56 @@ int http_compression_buffer_end(struct session *s, struct buffer **in, struct bu return to_forward; } +/* + * Alloc the comp_ctx + */ +static inline int init_comp_ctx(struct comp_ctx **comp_ctx) +{ +#ifdef USE_ZLIB + z_stream *strm; + + if (global.maxzlibmem > 0 && zlib_memory_available < 0) + zlib_memory_available = global.maxzlibmem * 1024 * 1024; /* Megabytes to bytes */ + + if (global.maxzlibmem > 0 && zlib_memory_available < sizeof(struct comp_ctx)) + return -1; +#endif + + if (unlikely(pool_comp_ctx == NULL)) + pool_comp_ctx = create_pool("comp_ctx", sizeof(struct comp_ctx), MEM_F_SHARED); + + *comp_ctx = pool_alloc2(pool_comp_ctx); + if (*comp_ctx == NULL) + return -1; +#ifdef USE_ZLIB + zlib_memory_available -= sizeof(struct comp_ctx); + + strm = &(*comp_ctx)->strm; + strm->zalloc = alloc_zlib; + strm->zfree = free_zlib; + strm->opaque = *comp_ctx; +#endif + return 0; +} + +/* + * Dealloc the comp_ctx + */ +static inline int deinit_comp_ctx(struct comp_ctx **comp_ctx) +{ + if (!*comp_ctx) + return 0; + + pool_free2(pool_comp_ctx, *comp_ctx); + *comp_ctx = NULL; + +#ifdef USE_ZLIB + zlib_memory_available += sizeof(struct comp_ctx); +#endif + + return 0; +} + /**************************** **** Identity algorithm **** @@ -298,7 +351,7 @@ int http_compression_buffer_end(struct session *s, struct buffer **in, struct bu /* * Init the identity algorithm */ -int identity_init(struct comp_ctx *comp_ctx, int level) +int identity_init(struct comp_ctx **comp_ctx, int level) { return 0; } @@ -336,7 +389,7 @@ int identity_reset(struct comp_ctx *comp_ctx) /* * Deinit the algorithm */ -int identity_end(struct comp_ctx *comp_ctx) +int identity_end(struct comp_ctx **comp_ctx) { return 0; } @@ -425,23 +478,24 @@ static void free_zlib(void *opaque, void *ptr) zlib_memory_available += pool->size; } - /************************** **** gzip algorithm **** ***************************/ -int gzip_init(struct comp_ctx *comp_ctx, int level) +int gzip_init(struct comp_ctx **comp_ctx, int level) { - z_stream *strm = &comp_ctx->strm; + z_stream *strm; - if (global.maxzlibmem > 0 && zlib_memory_available < 0) - zlib_memory_available = global.maxzlibmem * 1024 * 1024; /* Megabytes to bytes */ + if (init_comp_ctx(comp_ctx) < 0) + return -1; - strm->zalloc = alloc_zlib; - strm->zfree = free_zlib; - strm->opaque = comp_ctx; + strm = &(*comp_ctx)->strm; - if (deflateInit2(&comp_ctx->strm, level, Z_DEFLATED, global.tune.zlibwindowsize + 16, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) + if (deflateInit2(strm, level, Z_DEFLATED, global.tune.zlibwindowsize + 16, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) { + deinit_comp_ctx(comp_ctx); return -1; + } + + (*comp_ctx)->cur_lvl = level; return 0; } @@ -449,16 +503,21 @@ int gzip_init(struct comp_ctx *comp_ctx, int level) **** Deflate algorithm **** ***************************/ -int deflate_init(struct comp_ctx *comp_ctx, int level) +int deflate_init(struct comp_ctx **comp_ctx, int level) { - z_stream *strm = &comp_ctx->strm; + z_stream *strm; - strm->zalloc = alloc_zlib; - strm->zfree = free_zlib; - strm->opaque = comp_ctx; + if (init_comp_ctx(comp_ctx) < 0) + return -1; + + strm = &(*comp_ctx)->strm; - if (deflateInit(&comp_ctx->strm, level) != Z_OK) + if (deflateInit(strm, level) != Z_OK) { + deinit_comp_ctx(comp_ctx); return -1; + } + + (*comp_ctx)->cur_lvl = level; return 0; } @@ -538,14 +597,16 @@ int deflate_reset(struct comp_ctx *comp_ctx) return -1; } -int deflate_end(struct comp_ctx *comp_ctx) +int deflate_end(struct comp_ctx **comp_ctx) { - z_stream *strm = &comp_ctx->strm; + z_stream *strm = &(*comp_ctx)->strm; + int ret; - if (deflateEnd(strm) != Z_OK) - return -1; + ret = deflateEnd(strm); - return 0; + deinit_comp_ctx(comp_ctx); + + return ret; } #endif /* USE_ZLIB */ diff --git a/src/proto_http.c b/src/proto_http.c index e410b6dddc..8588b50e5f 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2105,8 +2105,6 @@ int select_compression_response_header(struct session *s, struct buffer *res) s->flags |= SN_COMP_READY; - s->comp_ctx.cur_lvl = global.tune.comp_maxlevel; - /* remove Content-Length header */ if ((msg->flags & HTTP_MSGF_CNT_LEN) && http_find_header2("Content-Length", 14, res->p, &txn->hdr_idx, &ctx)) http_remove_header2(msg, &txn->hdr_idx, &ctx); -- 2.39.5