From b7eba103048b82bc5740cf660c40948506354540 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 4 Dec 2006 02:20:02 +0100 Subject: [PATCH] [BUG] files were missing for hdr_idx in previous commit --- include/proto/hdr_idx.h | 62 +++++++++++++++++++++++++++++ include/types/hdr_idx.h | 84 ++++++++++++++++++++++++++++++++++++++++ src/hdr_idx.c | 86 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 include/proto/hdr_idx.h create mode 100644 include/types/hdr_idx.h create mode 100644 src/hdr_idx.c diff --git a/include/proto/hdr_idx.h b/include/proto/hdr_idx.h new file mode 100644 index 000000000..881a3eb62 --- /dev/null +++ b/include/proto/hdr_idx.h @@ -0,0 +1,62 @@ +/* + include/proto/hdr_idx.h + This file defines function prototypes for fast header indexation. + + Copyright (C) 2000-2006 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 + License as published by the Free Software Foundation, version 2.1 + exclusively. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _PROTO_HDR_IDX_H +#define _PROTO_HDR_IDX_H + +#include +#include + +/* + * Initialize the list pointers. + * list->size must already be set. If list->size is set and list->v is + * non-null, list->v is also initialized.. + */ +static inline void hdr_idx_init(struct hdr_idx *list) +{ + if (list->size && list->v) { + register struct hdr_idx_elem e = { .len=0, .cr=0, .next=0}; + list->v[0] = e; + } + list->tail = 0; + list->used = list->last = 1; +} + +/* + * Add a header entry to after element . is ignored when + * the list is empty or full. Common usage is to set to list->tail. + * + * Returns the position of the new entry in the list (from 1 to size-1), or 0 + * if the array is already full. An effort is made to fill the array linearly, + * but once the last entry has been used, we have to search for unused blocks, + * which takes much more time. For this reason, it's important to size is + * appropriately. + */ +int hdr_idx_add(int len, int cr, struct hdr_idx *list, int after); + +#endif /* _PROTO_HDR_IDX_H */ + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */ diff --git a/include/types/hdr_idx.h b/include/types/hdr_idx.h new file mode 100644 index 000000000..809ea8399 --- /dev/null +++ b/include/types/hdr_idx.h @@ -0,0 +1,84 @@ +/* + include/types/hdr_idx.h + This file defines everything related to fast header indexation. + + Copyright (C) 2000-2006 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 + License as published by the Free Software Foundation, version 2.1 + exclusively. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +/* + * The type of structure described here is a finite linked list used to + * reference small number of objects of small size. This is typically used + * to index HTTP headers within one request or response, in order to be able + * to add, remove, modify and check them in an efficient way. The overhead is + * very low : 32 bits are used per list element. This is enough to reference + * 32k headers of at most 64kB each, with one bit to indicate if the header + * is terminated by 1 or 2 chars. It may also evolve towards something like + * 1k headers of at most 64B for the name and 32kB of data + CR/CRLF. + * + * A future evolution of this concept may allow for fast header manipulation + * without data movement through the use of vectors. This is not yet possible + * in this version, whose goal is only to avoid parsing whole lines for each + * consultation. + * + */ + + +#ifndef _TYPES_HDR_IDX_H +#define _TYPES_HDR_IDX_H + +/* + * This describes one element of the hdr_idx array. + * It's a tiny linked list of at most 32k 32bit elements. The first one has a + * special meaning, it's used as the head of the list and cannod be removed. + * That way, we know that 'next==0' is not possible so we use it to indicate + * an end of list. Also, [0]->next always designates the head of the list. The + * first allocatable element is at 1. By convention, [0]->len indicates how + * many chars should be skipped in the original buffer before finding the first + * header. + * + */ + +struct hdr_idx_elem { + unsigned len :16; /* length of this header not counting CRLF. 0=unused entry. */ + unsigned cr : 1; /* CR present (1=CRLF, 0=LF). Total line size=len+cr+1. */ + unsigned next :15; /* offset of next header if len>0. 0=end of list. */ +}; + +/* + * This structure provides necessary information to store, find, remove + * index entries from a list. This list cannot reference more than 32k + * elements of 64k each. + */ +struct hdr_idx { + struct hdr_idx_elem *v; /* the array itself */ + short size; /* size of the array including the head */ + short used; /* # of elements really used (1..size) */ + short last; /* length of the allocated area (1..size) */ + signed short tail; /* last used element, 0..size-1 */ +}; + + + +#endif /* _TYPES_HDR_IDX_H */ + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */ diff --git a/src/hdr_idx.c b/src/hdr_idx.c new file mode 100644 index 000000000..da6b906c9 --- /dev/null +++ b/src/hdr_idx.c @@ -0,0 +1,86 @@ +/* + * Header indexation functions. + * + * Copyright 2000-2006 Willy Tarreau + * + * 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 +#include + + +/* + * Initialize the list pointers. + * list->size must already be set. If list->size is set and list->v is + * non-null, list->v is also initialized.. + */ +static inline void hdr_idx_init(struct hdr_idx *list) +{ + + if (list->size && list->v) { + register struct hdr_idx_elem e = { .len=0, .cr=0, .next=0}; + list->v[0] = e; + } + list->tail = 0; + list->used = list->last = 1; +} + +/* + * Add a header entry to after element . is ignored when + * the list is empty or full. Common usage is to set to list->tail. + * + * Returns the position of the new entry in the list (from 1 to size-1), or 0 + * if the array is already full. An effort is made to fill the array linearly, + * but once the last entry has been used, we have to search for unused blocks, + * which takes much more time. For this reason, it's important to size is + * appropriately. + */ +int hdr_idx_add(int len, int cr, struct hdr_idx *list, int after) +{ + register struct hdr_idx_elem e = { .len=0, .cr=0, .next=0}; + int new; + + e.len = len; + e.cr = cr; + + if (list->used == list->size) { + /* list is full */ + return -1; + } + + + if (list->last < list->size) { + /* list is not completely used, we can fill linearly */ + new = list->last++; + } else { + /* That's the worst situation : + * we have to scan the list for holes. We know that we + * will find a place because the list is not full. + */ + new = 1; + while (list->v[new].len) + new++; + } + + /* insert the new element between and the next one (or end) */ + e.next = list->v[after].next; + list->v[after].next = new; + + list->used++; + list->v[new] = e; + list->tail = new; + return new; +} + + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */