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.
diff --git a/include/proto/compression.h b/include/proto/compression.h
index cfab62a..1614edd 100644
--- a/include/proto/compression.h
+++ b/include/proto/compression.h
@@ -33,22 +33,21 @@
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 cf56e45..e4b1f27 100644
--- a/include/types/compression.h
+++ b/include/types/compression.h
@@ -50,11 +50,11 @@
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 284b7e8..e0d3c22 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -159,7 +159,7 @@
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 10fc4a6..d4b3d91 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -5442,7 +5442,7 @@
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 72c9996..c1e1afd 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 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 @@
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 @@
/* 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 @@
}
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 @@
*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 @@
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 @@
/*
* 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 @@
/*
* 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 @@
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 @@
**** 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 @@
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 e410b6d..8588b50 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2105,8 +2105,6 @@
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);