Merge branch 'pools' into merge-pools
diff --git a/Makefile b/Makefile
index c7017e5..37439c3 100644
--- a/Makefile
+++ b/Makefile
@@ -215,9 +215,9 @@
OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
- src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
+ src/checks.o src/queue.o src/client.o src/proxy.o \
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
- src/session.o src/hdr_idx.o src/ev_select.o src/acl.o
+ src/session.o src/hdr_idx.o src/ev_select.o src/acl.o src/memory.o
haproxy: $(OBJS) $(OPT_OBJS)
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
diff --git a/Makefile.bsd b/Makefile.bsd
index 76fe256..cc80040 100644
--- a/Makefile.bsd
+++ b/Makefile.bsd
@@ -85,10 +85,10 @@
OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
- src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
+ src/checks.o src/queue.o src/client.o src/proxy.o \
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o \
- src/ev_kqueue.o src/acl.o
+ src/ev_kqueue.o src/acl.o src/memory.o
all: haproxy
diff --git a/Makefile.osx b/Makefile.osx
index 15db775..5cf4f08 100644
--- a/Makefile.osx
+++ b/Makefile.osx
@@ -85,9 +85,10 @@
OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
- src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
+ src/checks.o src/queue.o src/client.o src/proxy.o \
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
- src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o src/acl.o
+ src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o src/acl.o \
+ src/memory.o
all: haproxy
diff --git a/include/common/appsession.h b/include/common/appsession.h
index 8fa681c..4687298 100644
--- a/include/common/appsession.h
+++ b/include/common/appsession.h
@@ -10,6 +10,7 @@
#include <common/config.h>
#include <common/hashpjw.h>
#include <common/list.h>
+#include <common/memory.h>
#include <types/task.h>
@@ -20,14 +21,11 @@
unsigned long int request_count;
} appsess;
-#define sizeof_appsess sizeof(struct appsessions)
-extern void **pool_appsess;
+extern struct pool_head *pool2_appsess;
struct app_pool {
- void **sessid;
- void **serverid;
- int ses_waste, ses_use, ses_msize;
- int ser_waste, ser_use, ser_msize;
+ struct pool_head *sessid;
+ struct pool_head *serverid;
};
extern struct app_pool apools;
diff --git a/include/common/config.h b/include/common/config.h
index e8d8ad2..85deeae 100644
--- a/include/common/config.h
+++ b/include/common/config.h
@@ -2,7 +2,7 @@
include/common/config.h
This files contains most of the user-configurable settings.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -39,6 +39,27 @@
# define CONFIG_HAP_MEM_OPTIM
#endif /* CONFIG_HAP_NO_MEM_OPTIM */
+/* CONFIG_HAP_MALLOC / CONFIG_HAP_CALLOC / CONFIG_HAP_FREE
+ * This macro allows to replace the malloc function with another one.
+ */
+#ifdef CONFIG_HAP_MALLOC
+#define MALLOC CONFIG_HAP_MALLOC
+#else
+#define MALLOC malloc
+#endif
+
+#ifdef CONFIG_HAP_CALLOC
+#define CALLOC CONFIG_HAP_CALLOC
+#else
+#define CALLOC calloc
+#endif
+
+#ifdef CONFIG_HAP_FREE
+#define FREE CONFIG_HAP_FREE
+#else
+#define FREE free
+#endif
+
/* CONFIG_HAP_INLINE_FD_SET
* This makes use of inline FD_* macros instead of calling equivalent
diff --git a/include/common/memory.h b/include/common/memory.h
index 820c1d9..835d79d 100644
--- a/include/common/memory.h
+++ b/include/common/memory.h
@@ -2,7 +2,7 @@
include/common/memory.h
Memory management definitions..
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -25,9 +25,8 @@
#include <stdlib.h>
#include <common/config.h>
+#include <common/mini-clist.h>
-#define sizeof_requri REQURI_LEN
-#define sizeof_capture CAPTURE_LEN
/*
* Returns a pointer to an area of <__len> bytes taken from the pool <pool> or
* dynamically allocated. In the first case, <__pool> is updated to point to
@@ -112,6 +111,91 @@
}
}
+
+/******* pools version 2 ********/
+
+#define MEM_F_SHARED 0x1
+
+struct pool_head {
+ void **free_list;
+ struct list list; /* list of all known pools */
+ unsigned int used; /* how many chunks are currently in use */
+ unsigned int allocated; /* how many chunks have been allocated */
+ unsigned int limit; /* hard limit on the number of chunks */
+ unsigned int minavail; /* how many chunks are expected to be used */
+ unsigned int size; /* chunk size */
+ unsigned int flags; /* MEM_F_* */
+ unsigned int users; /* number of pools sharing this zone */
+ char name[12]; /* name of the pool */
+};
+
+
+/* Allocate a new entry for pool <pool>, and return it for immediate use.
+ * NULL is returned if no memory is available for a new creation.
+ */
+void *pool_refill_alloc(struct pool_head *pool);
+
+/* Try to find an existing shared pool with the same characteristics and
+ * returns it, otherwise creates this one. NULL is returned if no memory
+ * is available for a new creation.
+ */
+struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags);
+
+/* Dump statistics on pools usage.
+ */
+void dump_pools(void);
+
+/*
+ * This function frees whatever can be freed in pool <pool>.
+ */
+void pool_flush2(struct pool_head *pool);
+
+/*
+ * This function frees whatever can be freed in all pools, but respecting
+ * the minimum thresholds imposed by owners.
+ */
+void pool_gc2();
+
+/*
+ * This function destroys a pull by freeing it completely.
+ * This should be called only under extreme circumstances.
+ */
+void *pool_destroy2(struct pool_head *pool);
+
+/*
+ * Returns a pointer to type <type> taken from the
+ * pool <pool_type> or dynamically allocated. In the
+ * first case, <pool_type> is updated to point to the
+ * next element in the list.
+ */
+#define pool_alloc2(pool) \
+({ \
+ void *__p; \
+ if ((__p = pool->free_list) == NULL) \
+ __p = pool_refill_alloc(pool); \
+ else { \
+ pool->free_list = *(void **)pool->free_list; \
+ pool->used++; \
+ } \
+ __p; \
+})
+
+/*
+ * Puts a memory area back to the corresponding pool.
+ * Items are chained directly through a pointer that
+ * is written in the beginning of the memory area, so
+ * there's no need for any carrier cell. This implies
+ * that each memory area is at least as big as one
+ * pointer.
+ */
+#define pool_free2(pool, ptr) \
+({ \
+ *(void **)ptr = (void *)pool->free_list; \
+ pool->free_list = (void *)ptr; \
+ pool->used--; \
+})
+
+
#endif /* _COMMON_MEMORY_H */
/*
diff --git a/include/import/tree.h b/include/import/tree.h
index 7c375e7..11ca6e0 100644
--- a/include/import/tree.h
+++ b/include/import/tree.h
@@ -2,6 +2,8 @@
* tree.h : tree manipulation macros and structures.
* (C) 2002 - Willy Tarreau - willy@ant-computing.com
*
+ * 2007/05/13: adapted to mempools v2.
+ *
*/
#ifndef __TREE_H__
@@ -51,8 +53,7 @@
struct tree64 *up; /* parent node. NULL = root */
};
-#define sizeof_tree64 (sizeof (struct tree64))
-extern void **pool_tree64;
+extern struct pool_head *pool2_tree64;
#define ULTREE_HEAD(l) struct ultree (l) = { .left=NULL, .right=NULL, .up=NULL, .low=0, .level=LONGBITS, .data=NULL }
#define ULTREE_INIT(l) { (l)->data = (l)->left = (l)->right = NULL; }
@@ -96,7 +97,7 @@
if (next == NULL) {
/* we'll have to insert our node here */
- *branch = new = (struct ulltree *)pool_alloc(tree64);
+ *branch = new = (struct ulltree *)pool_alloc2(pool2_tree64);
ULLTREE_INIT(new);
new->up = root;
new->value = x;
@@ -111,7 +112,7 @@
/* ok, now we know that we must insert between both. */
/* the new interconnect node */
- *branch = node = (struct ulltree *)pool_alloc(tree64); /* was <next> */
+ *branch = node = (struct ulltree *)pool_alloc2(pool2_tree64); /* was <next> */
ULLTREE_INIT(node);
node->up = root;
next->up = node;
@@ -139,7 +140,7 @@
/* the new leaf now */
node->level = m; /* set the level to the lowest common bit */
- new = (struct ulltree *)pool_alloc(tree64);
+ new = (struct ulltree *)pool_alloc2(pool2_tree64);
ULLTREE_INIT(new);
new->value = x;
new->level = ffs;
@@ -186,7 +187,7 @@
if (next == NULL) {
/* we'll have to insert our node here */
- *branch = new = (struct ultree *)pool_alloc(tree64);
+ *branch = new = (struct ultree *)pool_alloc2(pool2_tree64);
ULTREE_INIT(new);
new->up = root;
new->low = x;
@@ -200,7 +201,7 @@
/* ok, now we know that we must insert between both. */
/* the new interconnect node */
- *branch = node = (struct ultree *)pool_alloc(tree64); /* was <next> */
+ *branch = node = (struct ultree *)pool_alloc2(pool2_tree64); /* was <next> */
ULTREE_INIT(node);
node->up = root;
next->up = node;
@@ -228,7 +229,7 @@
/* the new leaf now */
node->level = m; /* set the level to the lowest common bit */
- new = (struct ultree *)pool_alloc(tree64);
+ new = (struct ultree *)pool_alloc2(pool2_tree64);
ULTREE_INIT(new);
new->low = x;
new->level = ffs;
@@ -279,7 +280,7 @@
if (next == NULL) {
/* we'll have to insert our node here */
- *branch = new =(struct ultree *)pool_alloc(tree64);
+ *branch = new =(struct ultree *)pool_alloc2(pool2_tree64);
UL2TREE_INIT(new);
new->up = root;
new->high = h;
@@ -308,7 +309,7 @@
/* ok, now we know that we must insert between both. */
/* the new interconnect node */
- *branch = node = (struct ultree *)pool_alloc(tree64); /* was <next> */
+ *branch = node = (struct ultree *)pool_alloc2(pool2_tree64); /* was <next> */
UL2TREE_INIT(node);
node->up = root;
next->up = node;
@@ -352,7 +353,7 @@
/* the new leaf now */
node->level = m; /* set the level to the lowest common bit */
- new = (struct ultree *)pool_alloc(tree64);
+ new = (struct ultree *)pool_alloc2(pool2_tree64);
UL2TREE_INIT(new);
new->high = h;
new->low = l;
@@ -456,7 +457,7 @@
goto __end; /* nothing left, don't delete the root node */ \
else { \
typeof (__root) __old; \
- pool_free(tree64, __ptr); \
+ pool_free2(pool2_tree64, __ptr); \
__old = __ptr; \
__ptr = __stack[__slen]; \
if (__ptr->left == __old) { \
@@ -506,7 +507,7 @@
goto __end; /* nothing left, don't delete the root node */ \
else { \
typeof (__root) __old; \
- pool_free(__type, __ptr); \
+ pool_free2(pool##__type, __ptr); \
__old = __ptr; \
__ptr = __stack[__slen]; \
if (__ptr->left == __old) { \
@@ -561,7 +562,7 @@
goto __end; /* nothing left, don't delete the root node */ \
else { \
typeof (__root) __old; \
- pool_free(tree64, __ptr); \
+ pool_free2(pool2_tree64, __ptr); \
__old = __ptr; \
__ptr = __stack[__slen]; \
if (__ptr->left == __old) { \
@@ -617,7 +618,7 @@
goto __end; /* nothing left, don't delete the root node */ \
else { \
typeof (__root) __old; \
- pool_free(tree64, __ptr); \
+ pool_free2(pool2_tree64, __ptr); \
__old = __ptr; \
__ptr = __stack[__slen]; \
if (__ptr->left == __old) { \
@@ -671,7 +672,7 @@
*/
down = node;
node = node->up;
- pool_free(tree64, down);
+ pool_free2(pool2_tree64, down);
if (node->data || node->up == NULL)
return node;
/* now we're sure we were sharing this empty node with another branch, let's find it */
@@ -684,7 +685,7 @@
down->up = node->up;
}
/* free the last node */
- pool_free(tree64, node);
+ pool_free2(pool2_tree64, node);
return down->up;
}
@@ -716,7 +717,7 @@
uplink = &up->right;
*uplink = down; /* we relink the lower branch above us or simply cut it */
- pool_free(tree64, node);
+ pool_free2(pool2_tree64, node);
node = up;
if (down)
down->up = node;
diff --git a/include/proto/buffers.h b/include/proto/buffers.h
index 6c39962..74efe8f 100644
--- a/include/proto/buffers.h
+++ b/include/proto/buffers.h
@@ -22,11 +22,19 @@
#ifndef _PROTO_BUFFERS_H
#define _PROTO_BUFFERS_H
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <common/config.h>
+#include <common/memory.h>
#include <types/buffers.h>
+extern struct pool_head *pool2_buffer;
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_buffer();
+
/* Initializes all fields in the buffer. The ->rlim field is initialized last
* so that the compiler can optimize it away if changed immediately after the
* call to this function.
diff --git a/include/proto/log.h b/include/proto/log.h
index 4ed56dd..1a02ec1 100644
--- a/include/proto/log.h
+++ b/include/proto/log.h
@@ -27,10 +27,13 @@
#include <syslog.h>
#include <common/config.h>
+#include <common/memory.h>
#include <types/log.h>
#include <types/proxy.h>
#include <types/session.h>
+extern struct pool_head *pool2_requri;
+
/*
* Displays the message on stderr with the date and pid. Overrides the quiet
* mode during startup.
diff --git a/include/proto/queue.h b/include/proto/queue.h
index 4370cb3..092747a 100644
--- a/include/proto/queue.h
+++ b/include/proto/queue.h
@@ -32,6 +32,9 @@
#include <types/server.h>
#include <types/task.h>
+extern struct pool_head *pool2_pendconn;
+
+int init_pendconn();
struct session *pendconn_get_next_sess(struct server *srv, struct proxy *px);
struct pendconn *pendconn_add(struct session *sess);
void pendconn_free(struct pendconn *p);
diff --git a/include/proto/session.h b/include/proto/session.h
index e3e5234..a18669e 100644
--- a/include/proto/session.h
+++ b/include/proto/session.h
@@ -2,7 +2,7 @@
include/proto/session.h
This file defines everything related to sessions.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -23,10 +23,15 @@
#define _PROTO_SESSION_H
#include <common/config.h>
+#include <common/memory.h>
#include <types/session.h>
+extern struct pool_head *pool2_session;
+
void session_free(struct session *s);
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_session();
#endif /* _PROTO_SESSION_H */
diff --git a/include/proto/task.h b/include/proto/task.h
index c594d52..6bee1b2 100644
--- a/include/proto/task.h
+++ b/include/proto/task.h
@@ -33,6 +33,10 @@
#include <types/task.h>
extern void *run_queue;
+extern struct pool_head *pool2_task;
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_task();
/* needed later */
void *tree_delete(void *node);
@@ -97,7 +101,7 @@
*/
static inline void task_free(struct task *t)
{
- pool_free(task, t);
+ pool_free2(pool2_task, t);
}
/* inserts <task> into its assigned wait queue, where it may already be. In this case, it
diff --git a/include/types/buffers.h b/include/types/buffers.h
index 9b781b8..09d1e34 100644
--- a/include/types/buffers.h
+++ b/include/types/buffers.h
@@ -73,9 +73,6 @@
char data[BUFSIZE];
};
-#define sizeof_buffer sizeof(struct buffer)
-extern void **pool_buffer;
-
#endif /* _TYPES_BUFFERS_H */
diff --git a/include/types/capture.h b/include/types/capture.h
index d0271a2..e37cc48 100644
--- a/include/types/capture.h
+++ b/include/types/capture.h
@@ -2,7 +2,7 @@
include/types/capture.h
This file defines everything related to captures.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,7 @@
#define _TYPES_CAPTURE_H
#include <common/config.h>
+#include <common/memory.h>
struct cap_hdr {
struct cap_hdr *next;
@@ -30,10 +31,10 @@
int namelen; /* length of the header name, to speed-up lookups */
int len; /* capture length, not including terminal zero */
int index; /* index in the output array */
- void *pool; /* pool of pre-allocated memory area of (len+1) bytes */
+ struct pool_head *pool; /* pool of pre-allocated memory area of (len+1) bytes */
};
-extern void **pool_capture;
+extern struct pool_head *pool2_capture;
#endif /* _TYPES_CAPTURE_H */
diff --git a/include/types/log.h b/include/types/log.h
index dc04e65..12f8e27 100644
--- a/include/types/log.h
+++ b/include/types/log.h
@@ -44,8 +44,6 @@
#define LW_REQHDR 1024 /* request header(s) */
#define LW_RSPHDR 2048 /* response header(s) */
-extern void **pool_requri;
-
#endif /* _TYPES_LOG_H */
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 532348e..bfbe631 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -140,8 +140,9 @@
int nb_req_cap, nb_rsp_cap; /* # of headers to be captured */
struct cap_hdr *req_cap; /* chained list of request headers to be captured */
struct cap_hdr *rsp_cap; /* chained list of response headers to be captured */
- void *req_cap_pool, *rsp_cap_pool; /* pools of pre-allocated char ** used to build the sessions */
- void *hdr_idx_pool; /* pools of pre-allocated int* used for headers indexing */
+ struct pool_head *req_cap_pool, /* pools of pre-allocated char ** used to build the sessions */
+ *rsp_cap_pool;
+ struct pool_head *hdr_idx_pool; /* pools of pre-allocated int* used for headers indexing */
char *req_add[MAX_NEWHDR], *rsp_add[MAX_NEWHDR]; /* headers to be added */
int grace; /* grace time after stop request */
char *check_req; /* HTTP or SSL request to use for PR_O_HTTP_CHK|PR_O_SSL3_CHK */
diff --git a/include/types/queue.h b/include/types/queue.h
index a8e7d8b..922aa92 100644
--- a/include/types/queue.h
+++ b/include/types/queue.h
@@ -34,10 +34,6 @@
struct server *srv; /* the server we are waiting for */
};
-#define sizeof_pendconn sizeof(struct pendconn)
-extern void **pool_pendconn;
-
-
#endif /* _TYPES_QUEUE_H */
/*
diff --git a/include/types/session.h b/include/types/session.h
index 7ef138f..819acfd 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -2,7 +2,7 @@
include/types/session.h
This file defines everything related to sessions.
- Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+ Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -123,10 +123,6 @@
};
-#define sizeof_session sizeof(struct session)
-extern void **pool_session;
-
-
#endif /* _TYPES_SESSION_H */
/*
diff --git a/include/types/task.h b/include/types/task.h
index 42699db..e0bbd6d 100644
--- a/include/types/task.h
+++ b/include/types/task.h
@@ -42,9 +42,6 @@
void *context; /* the task's context */
};
-#define sizeof_task sizeof(struct task)
-extern void **pool_task;
-
#endif /* _TYPES_TASK_H */
/*
diff --git a/src/appsession.c b/src/appsession.c
index 72b7e40..50554a5 100644
--- a/src/appsession.c
+++ b/src/appsession.c
@@ -2,6 +2,7 @@
* AppSession functions.
*
* Copyright 2004-2006 Alexander Lazic, Klaus Wagner
+ * Copyright 2006-2007 Willy Tarreau
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -17,6 +18,7 @@
#include <common/chtbl.h>
#include <common/config.h>
#include <common/list.h>
+#include <common/memory.h>
#include <common/time.h>
#include <types/buffers.h>
@@ -27,7 +29,7 @@
#include <proto/task.h>
-void **pool_appsess = NULL;
+struct pool_head *pool2_appsess;
struct app_pool apools;
int have_appsession;
@@ -72,30 +74,40 @@
struct proxy *p = proxy;
if (!initialized) {
+ pool2_appsess = create_pool("appsess", sizeof(appsess), MEM_F_SHARED);
+ if (pool2_appsess == NULL)
+ return -1;
+
if (!appsession_task_init()) {
+ int ser_msize, ses_msize;
+
apools.sessid = NULL;
apools.serverid = NULL;
- apools.ser_waste = 0;
- apools.ser_use = 0;
- apools.ser_msize = sizeof(void *);
- apools.ses_waste = 0;
- apools.ses_use = 0;
- apools.ses_msize = sizeof(void *);
+
+ ser_msize = sizeof(void *);
+ ses_msize = sizeof(void *);
while (p) {
s = p->srv;
- if (apools.ses_msize < p->appsession_len)
- apools.ses_msize = p->appsession_len;
+ if (ses_msize < p->appsession_len)
+ ses_msize = p->appsession_len;
while (s) {
idlen = strlen(s->id);
- if (apools.ser_msize < idlen)
- apools.ser_msize = idlen;
+ if (ser_msize < idlen)
+ ser_msize = idlen;
s = s->next;
}
p = p->next;
}
/* we use strings, so reserve space for '\0' */
- apools.ser_msize ++;
- apools.ses_msize ++;
+ ser_msize ++;
+ ses_msize ++;
+
+ apools.sessid = create_pool("sessid", ses_msize, MEM_F_SHARED);
+ if (!apools.sessid)
+ return -1;
+ apools.serverid = create_pool("serverid", ser_msize, MEM_F_SHARED);
+ if (!apools.serverid)
+ return -1;
}
else {
fprintf(stderr, "appsession_task_init failed\n");
@@ -111,15 +123,15 @@
static int initialized = 0;
struct task *t;
if (!initialized) {
- if ((t = pool_alloc(task)) == NULL)
+ if ((t = pool_alloc2(pool2_task)) == NULL)
return -1;
t->wq = NULL;
t->qlist.p = NULL;
t->state = TASK_IDLE;
t->context = NULL;
tv_ms_add(&t->expire, &now, TBLCHKINT);
- task_queue(t);
t->process = appsession_refresh;
+ task_queue(t);
initialized ++;
}
return 0;
@@ -174,6 +186,7 @@
p = p->next;
}
tv_ms_add(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
+ task_queue(t);
*next = t->expire;
} /* end appsession_refresh */
@@ -196,12 +209,12 @@
temp1 = (appsess *)data;
if (temp1->sessid)
- pool_free_to(apools.sessid, temp1->sessid);
+ pool_free2(apools.sessid, temp1->sessid);
if (temp1->serverid)
- pool_free_to(apools.serverid, temp1->serverid);
+ pool_free2(apools.serverid, temp1->serverid);
- pool_free(appsess, temp1);
+ pool_free2(pool2_appsess, temp1);
} /* end destroy */
void appsession_cleanup( void )
diff --git a/src/buffers.c b/src/buffers.c
index 5739fcf..658539c 100644
--- a/src/buffers.c
+++ b/src/buffers.c
@@ -15,9 +15,19 @@
#include <string.h>
#include <common/config.h>
+#include <common/memory.h>
#include <proto/buffers.h>
-void **pool_buffer = NULL;
+struct pool_head *pool2_buffer;
+
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_buffer()
+{
+ pool2_buffer = create_pool("buffer", sizeof(struct buffer), MEM_F_SHARED);
+ return pool2_buffer != NULL;
+}
+
/* writes <len> bytes from message <msg> to buffer <buf>. Returns 0 in case of
* success, or the number of bytes available otherwise.
diff --git a/src/capture.c b/src/capture.c
deleted file mode 100644
index c0c4a75..0000000
--- a/src/capture.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Capture variables and functions.
- *
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <stdlib.h>
-
-#include <common/config.h>
-#include <types/capture.h>
-
-void **pool_capture = NULL;
-
-
-/*
- * Local variables:
- * c-indent-level: 8
- * c-basic-offset: 8
- * End:
- */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 1edaa8f..5165474 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -824,6 +824,7 @@
hdr->name = strdup(args[3]);
hdr->namelen = strlen(args[3]);
hdr->len = atol(args[5]);
+ hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
hdr->index = curproxy->nb_req_cap++;
curproxy->req_cap = hdr;
curproxy->to_log |= LW_REQHDR;
@@ -846,6 +847,7 @@
hdr->name = strdup(args[3]);
hdr->namelen = strlen(args[3]);
hdr->len = atol(args[5]);
+ hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
hdr->index = curproxy->nb_rsp_cap++;
curproxy->rsp_cap = hdr;
curproxy->to_log |= LW_RSPHDR;
@@ -2401,6 +2403,20 @@
memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
}
+ /* The small pools required for the capture lists */
+ if (curproxy->nb_req_cap)
+ curproxy->req_cap_pool = create_pool("ptrcap",
+ curproxy->nb_req_cap * sizeof(char *),
+ MEM_F_SHARED);
+ if (curproxy->nb_rsp_cap)
+ curproxy->rsp_cap_pool = create_pool("ptrcap",
+ curproxy->nb_rsp_cap * sizeof(char *),
+ MEM_F_SHARED);
+
+ curproxy->hdr_idx_pool = create_pool("hdr_idx",
+ MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
+ MEM_F_SHARED);
+
/* for backwards compatibility with "listen" instances, if
* fullconn is not set but maxconn is set, then maxconn
* is used.
@@ -2488,7 +2504,7 @@
if (newsrv->maxconn > 0) {
struct task *t;
- if ((t = pool_alloc(task)) == NULL) {
+ if ((t = pool_alloc2(pool2_task)) == NULL) {
Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
return -1;
}
@@ -2535,7 +2551,7 @@
while (newsrv != NULL) {
/* should this server be checked ? */
if (newsrv->state & SRV_CHECKED) {
- if ((t = pool_alloc(task)) == NULL) {
+ if ((t = pool_alloc2(pool2_task)) == NULL) {
Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
return -1;
}
diff --git a/src/client.c b/src/client.c
index 52b281b..50a0f5d 100644
--- a/src/client.c
+++ b/src/client.c
@@ -41,6 +41,7 @@
#include <proto/log.h>
#include <proto/hdr_idx.h>
#include <proto/proto_http.h>
+#include <proto/session.h>
#include <proto/stream_sock.h>
#include <proto/task.h>
@@ -110,7 +111,7 @@
}
}
- if ((s = pool_alloc(session)) == NULL) { /* disable this proxy for a while */
+ if ((s = pool_alloc2(pool2_session)) == NULL) { /* disable this proxy for a while */
Alert("out of memory in event_accept().\n");
EV_FD_CLR(fd, DIR_RD);
p->state = PR_STIDLE;
@@ -127,18 +128,18 @@
(((struct sockaddr_in *)&addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr) {
if (p->mode == PR_MODE_TCP) {
close(cfd);
- pool_free(session, s);
+ pool_free2(pool2_session, s);
continue;
}
s->flags |= SN_MONITOR;
}
- if ((t = pool_alloc(task)) == NULL) { /* disable this proxy for a while */
+ if ((t = pool_alloc2(pool2_task)) == NULL) { /* disable this proxy for a while */
Alert("out of memory in event_accept().\n");
EV_FD_CLR(fd, DIR_RD);
p->state = PR_STIDLE;
close(cfd);
- pool_free(session, s);
+ pool_free2(pool2_session, s);
return 0;
}
@@ -146,8 +147,8 @@
if (cfd >= global.maxsock) {
Alert("accept(): not enough free sockets. Raise -n argument. Giving up.\n");
close(cfd);
- pool_free(task, t);
- pool_free(session, s);
+ pool_free2(pool2_task, t);
+ pool_free2(pool2_session, s);
return 0;
}
@@ -156,8 +157,8 @@
(char *) &one, sizeof(one)) == -1)) {
Alert("accept(): cannot set the socket in non blocking mode. Giving up\n");
close(cfd);
- pool_free(task, t);
- pool_free(session, s);
+ pool_free2(pool2_task, t);
+ pool_free2(pool2_session, s);
return 0;
}
@@ -229,15 +230,12 @@
txn->req.som = txn->req.eoh = 0; /* relative to the buffer */
txn->auth_hdr.len = -1;
- txn->hdr_idx.size = MAX_HTTP_HDR;
-
if (p->nb_req_cap > 0) {
- if ((txn->req.cap =
- pool_alloc_from(p->req_cap_pool, p->nb_req_cap*sizeof(char *)))
- == NULL) { /* no memory */
+ if ((txn->req.cap = pool_alloc2(p->req_cap_pool)) == NULL) {
+ /* no memory */
close(cfd); /* nothing can be done for this fd without memory */
- pool_free(task, t);
- pool_free(session, s);
+ pool_free2(pool2_task, t);
+ pool_free2(pool2_session, s);
return 0;
}
memset(txn->req.cap, 0, p->nb_req_cap*sizeof(char *));
@@ -245,30 +243,30 @@
if (p->nb_rsp_cap > 0) {
- if ((txn->rsp.cap =
- pool_alloc_from(p->rsp_cap_pool, p->nb_rsp_cap*sizeof(char *)))
- == NULL) { /* no memory */
+ if ((txn->rsp.cap = pool_alloc2(p->rsp_cap_pool)) == NULL) {
+ /* no memory */
if (txn->req.cap != NULL)
- pool_free_to(p->req_cap_pool, txn->req.cap);
+ pool_free2(p->req_cap_pool, txn->req.cap);
close(cfd); /* nothing can be done for this fd without memory */
- pool_free(task, t);
- pool_free(session, s);
+ pool_free2(pool2_task, t);
+ pool_free2(pool2_session, s);
return 0;
}
memset(txn->rsp.cap, 0, p->nb_rsp_cap*sizeof(char *));
}
- if ((txn->hdr_idx.v =
- pool_alloc_from(p->hdr_idx_pool, txn->hdr_idx.size*sizeof(*txn->hdr_idx.v)))
- == NULL) { /* no memory */
+ txn->hdr_idx.size = MAX_HTTP_HDR;
+
+ if ((txn->hdr_idx.v = pool_alloc2(p->hdr_idx_pool)) == NULL) {
+ /* no memory */
if (txn->rsp.cap != NULL)
- pool_free_to(p->rsp_cap_pool, txn->rsp.cap);
+ pool_free2(p->rsp_cap_pool, txn->rsp.cap);
if (txn->req.cap != NULL)
- pool_free_to(p->req_cap_pool, txn->req.cap);
+ pool_free2(p->req_cap_pool, txn->req.cap);
close(cfd); /* nothing can be done for this fd without memory */
- pool_free(task, t);
- pool_free(session, s);
+ pool_free2(pool2_task, t);
+ pool_free2(pool2_session, s);
return 0;
}
hdr_idx_init(&txn->hdr_idx);
@@ -346,16 +344,16 @@
write(1, trash, len);
}
- if ((s->req = pool_alloc(buffer)) == NULL) { /* no memory */
+ if ((s->req = pool_alloc2(pool2_buffer)) == NULL) { /* no memory */
if (txn->hdr_idx.v != NULL)
- pool_free_to(p->hdr_idx_pool, txn->hdr_idx.v);
+ pool_free2(p->hdr_idx_pool, txn->hdr_idx.v);
if (txn->rsp.cap != NULL)
- pool_free_to(p->rsp_cap_pool, txn->rsp.cap);
+ pool_free2(p->rsp_cap_pool, txn->rsp.cap);
if (txn->req.cap != NULL)
- pool_free_to(p->req_cap_pool, txn->req.cap);
+ pool_free2(p->req_cap_pool, txn->req.cap);
close(cfd); /* nothing can be done for this fd without memory */
- pool_free(task, t);
- pool_free(session, s);
+ pool_free2(pool2_task, t);
+ pool_free2(pool2_session, s);
return 0;
}
@@ -368,17 +366,17 @@
s->req->wto = s->be->srvtimeout;
s->req->cto = s->be->srvtimeout;
- if ((s->rep = pool_alloc(buffer)) == NULL) { /* no memory */
- pool_free(buffer, s->req);
+ if ((s->rep = pool_alloc2(pool2_buffer)) == NULL) { /* no memory */
+ pool_free2(pool2_buffer, s->req);
if (txn->hdr_idx.v != NULL)
- pool_free_to(p->hdr_idx_pool, txn->hdr_idx.v);
+ pool_free2(p->hdr_idx_pool, txn->hdr_idx.v);
if (txn->rsp.cap != NULL)
- pool_free_to(p->rsp_cap_pool, txn->rsp.cap);
+ pool_free2(p->rsp_cap_pool, txn->rsp.cap);
if (txn->req.cap != NULL)
- pool_free_to(p->req_cap_pool, txn->req.cap);
+ pool_free2(p->req_cap_pool, txn->req.cap);
close(cfd); /* nothing can be done for this fd without memory */
- pool_free(task, t);
- pool_free(session, s);
+ pool_free2(pool2_task, t);
+ pool_free2(pool2_session, s);
return 0;
}
diff --git a/src/haproxy.c b/src/haproxy.c
index 0acf75f..a86abeb 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -87,6 +87,7 @@
#include <proto/proxy.h>
#include <proto/queue.h>
#include <proto/server.h>
+#include <proto/session.h>
#include <proto/stream_sock.h>
#include <proto/task.h>
@@ -202,6 +203,7 @@
void sig_soft_stop(int sig)
{
soft_stop();
+ pool_gc2();
signal(sig, SIG_IGN);
}
@@ -211,6 +213,7 @@
void sig_pause(int sig)
{
pause_proxies();
+ pool_gc2();
signal(sig, sig_pause);
}
@@ -292,6 +295,9 @@
);
}
#endif
+ /* dump memory usage then free everything possible */
+ dump_pools();
+ pool_gc2();
}
#ifdef DEBUG_MEMORY
@@ -314,6 +320,7 @@
0 GRACE time
*/
fast_stop();
+ pool_gc2();
/* If we are killed twice, we decide to die*/
signal(sig, SIG_DFL);
}
@@ -326,6 +333,7 @@
0 GRACE time
*/
fast_stop();
+ pool_gc2();
/* If we are killed twice, we decide to die*/
signal(sig, SIG_DFL);
}
@@ -370,6 +378,10 @@
localtime((time_t *)&now.tv_sec);
start_date = now;
+ init_task();
+ init_session();
+ init_buffer();
+ init_pendconn();
init_proto_http();
cfg_polling_mechanism = POLL_USE_SELECT; /* select() is always available */
@@ -572,7 +584,7 @@
void deinit(void)
{
- struct proxy *p = proxy;
+ struct proxy *p = proxy, *p0;
struct cap_hdr *h,*h_next;
struct server *s,*s_next;
struct listener *l,*l_next;
@@ -608,7 +620,7 @@
h_next = h->next;
if (h->name)
free(h->name);
- pool_destroy(h->pool);
+ pool_destroy2(h->pool);
free(h);
h = h_next;
}/* end while(h) */
@@ -619,7 +631,7 @@
if (h->name)
free(h->name);
- pool_destroy(h->pool);
+ pool_destroy2(h->pool);
free(h);
h = h_next;
}/* end while(h) */
@@ -644,9 +656,11 @@
l = l_next;
}/* end while(l) */
- pool_destroy((void **) p->req_cap_pool);
- pool_destroy((void **) p->rsp_cap_pool);
+ pool_destroy2(p->req_cap_pool);
+ pool_destroy2(p->rsp_cap_pool);
+ p0 = p;
p = p->next;
+ free(p0);
}/* end while(p) */
if (global.chroot) free(global.chroot);
@@ -654,16 +668,17 @@
if (fdtab) free(fdtab);
- pool_destroy(pool_session);
- pool_destroy(pool_buffer);
- pool_destroy(pool_requri);
- pool_destroy(pool_task);
- pool_destroy(pool_capture);
- pool_destroy(pool_appsess);
+ pool_destroy2(pool2_session);
+ pool_destroy2(pool2_buffer);
+ pool_destroy2(pool2_requri);
+ pool_destroy2(pool2_task);
+ pool_destroy2(pool2_capture);
+ pool_destroy2(pool2_appsess);
+ pool_destroy2(pool2_pendconn);
if (have_appsession) {
- pool_destroy(apools.serverid);
- pool_destroy(apools.sessid);
+ pool_destroy2(apools.serverid);
+ pool_destroy2(apools.sessid);
}
} /* end deinit() */
diff --git a/src/memory.c b/src/memory.c
new file mode 100644
index 0000000..8009227
--- /dev/null
+++ b/src/memory.c
@@ -0,0 +1,187 @@
+/*
+ * Memory management functions.
+ *
+ * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <common/config.h>
+#include <common/memory.h>
+#include <common/mini-clist.h>
+#include <common/standard.h>
+
+#include <proto/log.h>
+
+static struct list pools = LIST_HEAD_INIT(pools);
+
+/* Try to find an existing shared pool with the same characteristics and
+ * returns it, otherwise creates this one. NULL is returned if no memory
+ * is available for a new creation.
+ */
+struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
+{
+ struct pool_head *pool;
+ struct pool_head *entry;
+ struct list *start;
+ unsigned int align;
+
+ /* We need to store at least a (void *) in the chunks. Since we know
+ * that the malloc() function will never return such a small size,
+ * let's round the size up to something slightly bigger, in order to
+ * ease merging of entries. Note that the rounding is a power of two.
+ */
+
+ align = 16;
+ size = (size + align - 1) & -align;
+
+ start = &pools;
+ pool = NULL;
+
+ list_for_each_entry(entry, &pools, list) {
+ if (entry->size == size) {
+ /* either we can share this place and we take it, or
+ * we look for a sharable one or for the next position
+ * before which we will insert a new one.
+ */
+ if (flags & entry->flags & MEM_F_SHARED) {
+ /* we can share this one */
+ pool = entry;
+ break;
+ }
+ }
+ else if (entry->size > size) {
+ /* insert before this one */
+ start = &entry->list;
+ break;
+ }
+ }
+
+ if (!pool) {
+ pool = CALLOC(1, sizeof(*pool));
+ if (!pool)
+ return NULL;
+ if (name)
+ strlcpy2(pool->name, name, sizeof(pool->name));
+ pool->size = size;
+ pool->flags = flags;
+ LIST_ADDQ(start, &pool->list);
+ }
+ pool->users++;
+ return pool;
+}
+
+/* Allocate a new entry for pool <pool>, and return it for immediate use.
+ * NULL is returned if no memory is available for a new creation. A call
+ * to the garbage collector is performed before returning NULL.
+ */
+void *pool_refill_alloc(struct pool_head *pool)
+{
+ void *ret;
+
+ if (pool->limit && (pool->allocated >= pool->limit))
+ return NULL;
+ ret = MALLOC(pool->size);
+ if (!ret) {
+ pool_gc2();
+ ret = MALLOC(pool->size);
+ if (!ret)
+ return NULL;
+ }
+ pool->allocated++;
+ pool->used++;
+ return ret;
+}
+
+/*
+ * This function frees whatever can be freed in pool <pool>.
+ */
+void pool_flush2(struct pool_head *pool)
+{
+ void *temp, *next;
+ if (!pool)
+ return;
+
+ next = pool->free_list;
+ while (next) {
+ temp = next;
+ next = *(void **)temp;
+ pool->allocated--;
+ FREE(temp);
+ }
+ pool->free_list = next;
+
+ /* here, we should have pool->allocate == pool->used */
+}
+
+/*
+ * This function frees whatever can be freed in all pools, but respecting
+ * the minimum thresholds imposed by owners.
+ */
+void pool_gc2()
+{
+ struct pool_head *entry;
+ list_for_each_entry(entry, &pools, list) {
+ void *temp, *next;
+ //qfprintf(stderr, "Flushing pool %s\n", entry->name);
+ next = entry->free_list;
+ while (next &&
+ entry->allocated > entry->minavail &&
+ entry->allocated > entry->used) {
+ temp = next;
+ next = *(void **)temp;
+ entry->allocated--;
+ FREE(temp);
+ }
+ entry->free_list = next;
+ }
+}
+
+/*
+ * This function destroys a pull by freeing it completely.
+ * This should be called only under extreme circumstances.
+ * It always returns NULL, easing the clearing of the old pointer.
+ */
+void *pool_destroy2(struct pool_head *pool)
+{
+ if (pool) {
+ pool_flush2(pool);
+ FREE(pool);
+ }
+ return NULL;
+}
+
+/* Dump statistics on pools usage.
+ */
+void dump_pools(void)
+{
+ struct pool_head *entry;
+ unsigned long allocated, used;
+ int nbpools;
+
+ allocated = used = nbpools = 0;
+ qfprintf(stderr, "Dumping pools usage.\n");
+ list_for_each_entry(entry, &pools, list) {
+ qfprintf(stderr, " - Pool %s (%d bytes) : %d allocated (%lu bytes), %d used, %d users%s\n",
+ entry->name, entry->size, entry->allocated,
+ entry->size * entry->allocated, entry->used,
+ entry->users, (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
+
+ allocated += entry->allocated * entry->size;
+ used += entry->used * entry->size;
+ nbpools++;
+ }
+ qfprintf(stderr, "Total: %d pools, %lu bytes allocated, %lu used.\n",
+ nbpools, allocated, used);
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/src/proto_http.c b/src/proto_http.c
index d1bfdcf..4e9e683 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -243,6 +243,10 @@
FD_SET(*tmp, url_encode_map);
tmp++;
}
+
+ /* memory allocations */
+ pool2_requri = create_pool("requri", REQURI_LEN, MEM_F_SHARED);
+ pool2_capture = create_pool("capture", CAPTURE_LEN, MEM_F_SHARED);
}
/*
@@ -624,7 +628,8 @@
const char sess_set_cookie[8] = "N1I3PD5R"; /* No set-cookie, unknown, Set-Cookie Inserted, unknown,
Set-cookie seen and left unchanged (passive), Set-cookie Deleted,
unknown, Set-cookie Rewritten */
-void **pool_requri = NULL;
+struct pool_head *pool2_requri;
+struct pool_head *pool2_capture;
/*
* send a log for the session when we have enough info about it.
@@ -770,7 +775,7 @@
(strncasecmp(sol, h->name, h->namelen) == 0)) {
if (cap[h->index] == NULL)
cap[h->index] =
- pool_alloc_from(h->pool, h->len + 1);
+ pool_alloc2(h->pool);
if (cap[h->index] == NULL) {
Alert("HTTP capture : out of memory.\n");
@@ -1592,7 +1597,7 @@
*/
if (unlikely(t->logs.logwait & LW_REQ)) {
/* we have a complete HTTP request that we must log */
- if ((txn->uri = pool_alloc(requri)) != NULL) {
+ if ((txn->uri = pool_alloc2(pool2_requri)) != NULL) {
int urilen = msg->sl.rq.l;
if (urilen >= REQURI_LEN)
@@ -4169,7 +4174,7 @@
memcmp(p1, t->fe->capture_name, t->fe->capture_namelen) == 0) {
int log_len = p4 - p1;
- if ((txn->cli_cookie = pool_alloc(capture)) == NULL) {
+ if ((txn->cli_cookie = pool_alloc2(pool2_capture)) == NULL) {
Alert("HTTP logging : out of memory.\n");
} else {
if (log_len > t->fe->capture_len)
@@ -4298,7 +4303,7 @@
asession_temp = &local_asession;
- if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
+ if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) {
Alert("Not enough memory process_cli():asession->sessid:malloc().\n");
send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n");
return;
@@ -4310,9 +4315,9 @@
/* only do insert, if lookup fails */
if (chtbl_lookup(&(t->be->htbl_proxy), (void *) &asession_temp) != 0) {
- if ((asession_temp = pool_alloc(appsess)) == NULL) {
+ if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) {
/* free previously allocated memory */
- pool_free_to(apools.sessid, local_asession.sessid);
+ pool_free2(apools.sessid, local_asession.sessid);
Alert("Not enough memory process_cli():asession:calloc().\n");
send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n");
return;
@@ -4323,7 +4328,7 @@
chtbl_insert(&(t->be->htbl_proxy), (void *) asession_temp);
} else {
/* free previously allocated memory */
- pool_free_to(apools.sessid, local_asession.sessid);
+ pool_free2(apools.sessid, local_asession.sessid);
}
if (asession_temp->serverid == NULL) {
@@ -4704,7 +4709,7 @@
memcmp(p1, t->be->capture_name, t->be->capture_namelen) == 0) {
int log_len = p4 - p1;
- if ((txn->srv_cookie = pool_alloc(capture)) == NULL) {
+ if ((txn->srv_cookie = pool_alloc2(pool2_capture)) == NULL) {
Alert("HTTP logging : out of memory.\n");
}
@@ -4771,7 +4776,7 @@
size_t server_id_len = strlen(t->srv->id) + 1;
asession_temp = &local_asession;
- if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
+ if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) {
Alert("Not enough Memory process_srv():asession->sessid:malloc().\n");
send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n");
return;
@@ -4782,7 +4787,7 @@
/* only do insert, if lookup fails */
if (chtbl_lookup(&(t->be->htbl_proxy), (void *) &asession_temp) != 0) {
- if ((asession_temp = pool_alloc(appsess)) == NULL) {
+ if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) {
Alert("Not enough Memory process_srv():asession:calloc().\n");
send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession:calloc().\n");
return;
@@ -4793,11 +4798,11 @@
}/* end if (chtbl_lookup()) */
else {
/* free wasted memory */
- pool_free_to(apools.sessid, local_asession.sessid);
+ pool_free2(apools.sessid, local_asession.sessid);
} /* end else from if (chtbl_lookup()) */
if (asession_temp->serverid == NULL) {
- if ((asession_temp->serverid = pool_alloc_from(apools.serverid, apools.ser_msize)) == NULL) {
+ if ((asession_temp->serverid = pool_alloc2(apools.serverid)) == NULL) {
Alert("Not enough Memory process_srv():asession->sessid:malloc().\n");
send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n");
return;
@@ -4941,7 +4946,7 @@
/* First try if we already have an appsession */
asession_temp = &local_asession;
- if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
+ if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) {
Alert("Not enough memory process_cli():asession_temp->sessid:calloc().\n");
send_log(t->be, LOG_ALERT, "Not enough Memory process_cli():asession_temp->sessid:calloc().\n");
return;
@@ -4954,9 +4959,9 @@
/* only do insert, if lookup fails */
if (chtbl_lookup(&(t->be->htbl_proxy), (void *)&asession_temp)) {
- if ((asession_temp = pool_alloc(appsess)) == NULL) {
+ if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) {
/* free previously allocated memory */
- pool_free_to(apools.sessid, local_asession.sessid);
+ pool_free2(apools.sessid, local_asession.sessid);
Alert("Not enough memory process_cli():asession:calloc().\n");
send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n");
return;
@@ -4967,7 +4972,7 @@
}
else {
/* free previously allocated memory */
- pool_free_to(apools.sessid, local_asession.sessid);
+ pool_free2(apools.sessid, local_asession.sessid);
}
tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
diff --git a/src/proxy.c b/src/proxy.c
index dd7f993..7d4b2ec 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -19,6 +19,7 @@
#include <common/defaults.h>
#include <common/compat.h>
#include <common/config.h>
+#include <common/memory.h>
#include <common/time.h>
#include <types/global.h>
@@ -230,6 +231,8 @@
listeners--;
}
p->state = PR_STSTOPPED;
+ /* try to free more memory */
+ pool_gc2();
}
else {
tv_bound(next, &p->stop_time);
diff --git a/src/queue.c b/src/queue.c
index 37d3ed8..a4670a8 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -11,6 +11,7 @@
*/
#include <common/config.h>
+#include <common/memory.h>
#include <common/time.h>
#include <types/proxy.h>
@@ -21,7 +22,14 @@
#include <proto/task.h>
-void **pool_pendconn = NULL;
+struct pool_head *pool2_pendconn;
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_pendconn()
+{
+ pool2_pendconn = create_pool("pendconn", sizeof(struct pendconn), MEM_F_SHARED);
+ return pool2_pendconn != NULL;
+}
/* returns the effective dynamic maxconn for a server, considering the minconn
* and the proxy's usage relative to its dynamic connections limit. It is
@@ -98,7 +106,7 @@
{
struct pendconn *p;
- p = pool_alloc(pendconn);
+ p = pool_alloc2(pool2_pendconn);
if (!p)
return NULL;
@@ -136,7 +144,7 @@
else
p->sess->be->nbpend--;
p->sess->be->totpend--;
- pool_free(pendconn, p);
+ pool_free2(pool2_pendconn, p);
}
diff --git a/src/session.c b/src/session.c
index 21d3480..d13f995 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1,7 +1,7 @@
/*
* Server management functions.
*
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,12 +21,14 @@
#include <types/proxy.h>
#include <types/server.h>
+#include <proto/buffers.h>
#include <proto/hdr_idx.h>
+#include <proto/log.h>
#include <proto/session.h>
#include <proto/queue.h>
-void **pool_session = NULL;
+struct pool_head *pool2_session;
/*
* frees the context associated to a session. It must have been removed first.
@@ -38,38 +40,46 @@
if (s->pend_pos)
pendconn_free(s->pend_pos);
if (s->req)
- pool_free(buffer, s->req);
+ pool_free2(pool2_buffer, s->req);
if (s->rep)
- pool_free(buffer, s->rep);
+ pool_free2(pool2_buffer, s->rep);
if (txn->hdr_idx.v != NULL)
- pool_free_to(s->fe->hdr_idx_pool, txn->hdr_idx.v);
+ pool_free2(s->fe->hdr_idx_pool, txn->hdr_idx.v);
if (txn->rsp.cap != NULL) {
struct cap_hdr *h;
for (h = s->fe->rsp_cap; h; h = h->next) {
if (txn->rsp.cap[h->index] != NULL)
- pool_free_to(h->pool, txn->rsp.cap[h->index]);
+ pool_free2(h->pool, txn->rsp.cap[h->index]);
}
- pool_free_to(s->fe->rsp_cap_pool, txn->rsp.cap);
+ pool_free2(s->fe->rsp_cap_pool, txn->rsp.cap);
}
if (txn->req.cap != NULL) {
struct cap_hdr *h;
for (h = s->fe->req_cap; h; h = h->next) {
if (txn->req.cap[h->index] != NULL)
- pool_free_to(h->pool, txn->req.cap[h->index]);
+ pool_free2(h->pool, txn->req.cap[h->index]);
}
- pool_free_to(s->fe->req_cap_pool, txn->req.cap);
+ pool_free2(s->fe->req_cap_pool, txn->req.cap);
}
if (txn->uri)
- pool_free(requri, txn->uri);
+ pool_free2(pool2_requri, txn->uri);
if (txn->cli_cookie)
- pool_free(capture, txn->cli_cookie);
+ pool_free2(pool2_capture, txn->cli_cookie);
if (txn->srv_cookie)
- pool_free(capture, txn->srv_cookie);
+ pool_free2(pool2_capture, txn->srv_cookie);
- pool_free(session, s);
+ pool_free2(pool2_session, s);
+}
+
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_session()
+{
+ pool2_session = create_pool("session", sizeof(struct session), MEM_F_SHARED);
+ return pool2_session != NULL;
}
diff --git a/src/task.c b/src/task.c
index 6190670..7f6e0e7 100644
--- a/src/task.c
+++ b/src/task.c
@@ -11,6 +11,7 @@
*/
#include <common/config.h>
+#include <common/memory.h>
#include <common/mini-clist.h>
#include <common/standard.h>
#include <common/time.h>
@@ -23,15 +24,22 @@
#include <import/bitops.h>
#include <import/tree.h>
-
-void **pool_task= NULL;
-void **pool_tree64 = NULL;
static struct ultree *stack[LLONGBITS];
+struct pool_head *pool2_task, *pool2_tree64;
+
UL2TREE_HEAD(timer_wq);
void *eternity_queue = NULL;
void *run_queue = NULL;
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_task()
+{
+ pool2_task = create_pool("task", sizeof(struct task), MEM_F_SHARED);
+ pool2_tree64 = create_pool("tree64", sizeof(struct tree64), MEM_F_SHARED);
+ return pool2_task && pool2_tree64;
+}
+
struct ultree *ul2tree_insert(struct ultree *root, unsigned long h, unsigned long l)
{
return __ul2tree_insert(root, h, l);