Merge branch 'pools' into merge-pools

This commit is contained in:
Willy Tarreau 2007-05-14 02:11:56 +02:00
commit 315bff5183
31 changed files with 556 additions and 195 deletions

View File

@ -215,9 +215,9 @@ all: haproxy
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)

View File

@ -85,10 +85,10 @@ LDFLAGS = -g
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

View File

@ -85,9 +85,10 @@ LDFLAGS = -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386
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

View File

@ -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 @@ typedef struct appsessions {
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;

View File

@ -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

View File

@ -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 @@ static inline void pool_destroy(void **pool)
}
}
/******* 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 */
/*

View File

@ -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 {
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 @@ inline static struct ulltree *__ulltree_insert(struct ulltree *root, unsigned lo
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 @@ inline static struct ulltree *__ulltree_insert(struct ulltree *root, unsigned lo
/* 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 @@ inline static struct ulltree *__ulltree_insert(struct ulltree *root, unsigned lo
/* 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 @@ inline static struct ultree *__ultree_insert(struct ultree *root, unsigned long
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 @@ inline static struct ultree *__ultree_insert(struct ultree *root, unsigned long
/* 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 @@ inline static struct ultree *__ultree_insert(struct ultree *root, unsigned long
/* 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 @@ inline static struct ultree *__ul2tree_insert(struct ultree *root, unsigned long
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 @@ inline static struct ultree *__ul2tree_insert(struct ultree *root, unsigned long
/* 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 @@ inline static struct ultree *__ul2tree_insert(struct ultree *root, unsigned long
/* 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 @@ __right: \
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 @@ __right: \
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 @@ __right: \
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 @@ __right: \
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 @@ inline static void *__tree_delete_only_one(void *firstnode) {
*/
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 @@ inline static void *__tree_delete_only_one(void *firstnode) {
down->up = node->up;
}
/* free the last node */
pool_free(tree64, node);
pool_free2(pool2_tree64, node);
return down->up;
}
@ -716,7 +717,7 @@ inline static void *__tree_delete(void *firstnode) {
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;

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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 */

View File

@ -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 struct task *task_delete(struct task *t)
*/
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

View File

@ -73,9 +73,6 @@ struct buffer {
char data[BUFSIZE];
};
#define sizeof_buffer sizeof(struct buffer)
extern void **pool_buffer;
#endif /* _TYPES_BUFFERS_H */

View File

@ -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 @@ struct cap_hdr {
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 */

View File

@ -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 */

View File

@ -140,8 +140,9 @@ struct proxy {
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 */

View File

@ -34,10 +34,6 @@ struct pendconn {
struct server *srv; /* the server we are waiting for */
};
#define sizeof_pendconn sizeof(struct pendconn)
extern void **pool_pendconn;
#endif /* _TYPES_QUEUE_H */
/*

View File

@ -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 @@ struct session {
};
#define sizeof_session sizeof(struct session)
extern void **pool_session;
#endif /* _TYPES_SESSION_H */
/*

View File

@ -42,9 +42,6 @@ struct task {
void *context; /* the task's context */
};
#define sizeof_task sizeof(struct task)
extern void **pool_task;
#endif /* _TYPES_TASK_H */
/*

View File

@ -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 @@ int appsession_init(void)
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 @@ int appsession_task_init(void)
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 @@ void appsession_refresh(struct task *t, struct timeval *next)
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 @@ void destroy(void *data) {
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 )

View File

@ -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.

View File

@ -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:
*/

View File

@ -824,6 +824,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
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 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
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 @@ int readcfgfile(const char *file)
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 @@ int readcfgfile(const char *file)
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 @@ int readcfgfile(const char *file)
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;
}

View File

@ -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 @@ int event_accept(int fd) {
}
}
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 @@ int event_accept(int fd) {
(((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 @@ int event_accept(int fd) {
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 @@ int event_accept(int fd) {
(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 @@ int event_accept(int fd) {
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 @@ int event_accept(int fd) {
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 @@ int event_accept(int fd) {
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 @@ int event_accept(int fd) {
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;
}

View File

@ -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 usage(char *name)
void sig_soft_stop(int sig)
{
soft_stop();
pool_gc2();
signal(sig, SIG_IGN);
}
@ -211,6 +213,7 @@ void sig_soft_stop(int sig)
void sig_pause(int sig)
{
pause_proxies();
pool_gc2();
signal(sig, sig_pause);
}
@ -292,6 +295,9 @@ void dump(int sig)
);
}
#endif
/* dump memory usage then free everything possible */
dump_pools();
pool_gc2();
}
#ifdef DEBUG_MEMORY
@ -314,6 +320,7 @@ void sig_int(int sig)
0 GRACE time
*/
fast_stop();
pool_gc2();
/* If we are killed twice, we decide to die*/
signal(sig, SIG_DFL);
}
@ -326,6 +333,7 @@ void sig_term(int sig)
0 GRACE time
*/
fast_stop();
pool_gc2();
/* If we are killed twice, we decide to die*/
signal(sig, SIG_DFL);
}
@ -370,6 +378,10 @@ void init(int argc, char **argv)
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 init(int argc, char **argv)
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 @@ void deinit(void)
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 @@ void deinit(void)
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 @@ void deinit(void)
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 @@ void deinit(void)
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() */

187
src/memory.c Normal file
View File

@ -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:
*/

View File

@ -243,6 +243,10 @@ void init_proto_http()
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_cookie[4] = "NIDV"; /* No cookie, Invalid cookie, cookie fo
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 @@ void capture_headers(char *som, struct hdr_idx *idx,
(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 @@ int process_cli(struct session *t)
*/
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 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
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 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
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 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
/* 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 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
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 @@ void manage_server_side_cookies(struct session *t, struct buffer *rtr)
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 @@ void manage_server_side_cookies(struct session *t, struct buffer *rtr)
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 @@ void manage_server_side_cookies(struct session *t, struct buffer *rtr)
/* 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 @@ void manage_server_side_cookies(struct session *t, struct buffer *rtr)
}/* 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 @@ void get_srv_from_appsession(struct session *t, const char *begin, int len)
/* 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 @@ void get_srv_from_appsession(struct session *t, const char *begin, int len)
/* 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 @@ void get_srv_from_appsession(struct session *t, const char *begin, int len)
}
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);

View File

@ -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 @@ void maintain_proxies(struct timeval *next)
listeners--;
}
p->state = PR_STSTOPPED;
/* try to free more memory */
pool_gc2();
}
else {
tv_bound(next, &p->stop_time);

View File

@ -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 *pendconn_add(struct session *sess)
{
struct pendconn *p;
p = pool_alloc(pendconn);
p = pool_alloc2(pool2_pendconn);
if (!p)
return NULL;
@ -136,7 +144,7 @@ void pendconn_free(struct pendconn *p)
else
p->sess->be->nbpend--;
p->sess->be->totpend--;
pool_free(pendconn, p);
pool_free2(pool2_pendconn, p);
}

View File

@ -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 @@ void session_free(struct session *s)
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;
}

View File

@ -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);