joes 2003/05/02 22:22:34
Modified: . Makefile.am
build README
env mod_apreq.c
src apreq_tables.c apreq_tables.h
t Makefile.am cookie.c tables.c test_apreq.h
testall.c
Added: t performance.c
Log:
Simplify table API a bit & add performance tests.
Revision Changes Path
1.6 +1 -1 httpd-apreq-2/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /home/cvs/httpd-apreq-2/Makefile.am,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- Makefile.am 19 Apr 2003 09:42:08 -0000 1.5
+++ Makefile.am 3 May 2003 05:22:33 -0000 1.6
@@ -3,4 +3,4 @@
EXTRA_DIST = INSTALL
test: check
- t/testall
\ No newline at end of file
+ t/testall -v
1.2 +5 -6 httpd-apreq-2/build/README
Index: README
===================================================================
RCS file: /home/cvs/httpd-apreq-2/build/README,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- README 29 Apr 2003 16:49:14 -0000 1.1
+++ README 3 May 2003 05:22:33 -0000 1.2
@@ -4,7 +4,7 @@
-UPDATING THE httpd-apreq HOME PAGE:
+UPDATING THE httpd-apreq SITE:
RedHat Linux:
1) Download and install j2re and j2sdk rpms from Sun's
@@ -16,8 +16,8 @@
http://ant.apache.org/bindownload.cgi
- I just expanded the tar.gz file in /usr/java/ant, which
- is alongside the jre and jdk directory trees.
+ (I just expanded the tar.gz file in /usr/java/ant, which
+ is alongside the jre and jdk directory trees.)
3) Prep the (bash) environment:
@@ -28,9 +28,8 @@
4) Check out httpd-site from cvs.apache.org and run
$ cd httpd-site
- $ emacs xdocs/apreq/index.html
+ $ emacs xdocs/apreq
$ ant
- $ cvs commit -m "Added info on public cvs access, snapshots and list
- archives for apreq." xdocs/apreq/index.html docs/apreq/index.html
+ $ cvs commit -m "..." xdocs/apreq/ docs/apreq/
5) Wait 24 hours for the changes to appear on the website.
1.11 +9 -0 httpd-apreq-2/env/mod_apreq.c
Index: mod_apreq.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/env/mod_apreq.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- mod_apreq.c 25 Apr 2003 03:17:47 -0000 1.10
+++ mod_apreq.c 3 May 2003 05:22:33 -0000 1.11
@@ -135,6 +135,8 @@
return c->jar;
}
+
+
static void *env_request(void *ctx, void *req)
{
dR;
@@ -143,9 +145,16 @@
if (req != NULL) {
apreq_request_t *oldreq = c->req;
+ /* XXX: this needs to be subrequest-friendly */
if (oldreq == NULL) {
dAPREQ_LOG;
ap_filter_rec_t *f = ap_get_input_filter_handle(filter_name);
+ if (r->main) {
+ struct env_ctx *n = apreq_note(r->main);
+ oldreq = n->req;
+ }
+
+
apreq_log(APREQ_DEBUG 0, r, "Adding APREQ filter to input
chain");
/* XXX: SOMEHOW INJECT APREQ INPUT FILTER */
ap_add_input_filter_handle(f, NULL, r, r->connection);
1.28 +100 -194 httpd-apreq-2/src/apreq_tables.c
Index: apreq_tables.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- apreq_tables.c 29 Apr 2003 17:54:48 -0000 1.27
+++ apreq_tables.c 3 May 2003 05:22:33 -0000 1.28
@@ -69,13 +69,17 @@
#include "apr_signal.h"
/********************* table_entry structure ********************/
+#define CS_TYPE apr_uint32_t
+#define CS_BYTES 4
+#define OFFSET ((CS_BYTES-1) * 8)
+
/* private struct */
typedef struct apreq_table_entry_t {
const apreq_value_t *val;
const char *key; /* = val->name : saves a ptr deref */
- apr_uint32_t checksum;
+ CS_TYPE checksum;
enum { RED, BLACK } color;
int tree[4]; /* LEFT RIGHT UP NEXT */
} apreq_table_entry_t;
@@ -99,25 +103,21 @@
#define TABLE_HASH_SIZE 16
#define TABLE_INDEX_MASK 0x0f
#define TABLE_HASH(c) (TABLE_INDEX_MASK & (unsigned char)(c))
+
+
#define COMPUTE_KEY_CHECKSUM(k, checksum) \
{ \
- apr_uint32_t c = (apr_uint32_t)*(k); \
+ CS_TYPE c = (CS_TYPE)*(k); \
+ int j = 0; \
(checksum) = c; \
- (checksum) <<= 8; \
- if (c) { \
- c = (apr_uint32_t)*++(k); \
- checksum |= c; \
- } \
- (checksum) <<= 8; \
- if (c) { \
- c = (apr_uint32_t)*++(k); \
- checksum |= c; \
- } \
- (checksum) <<= 8; \
- if (c) { \
- c = (apr_uint32_t)*++(k); \
- checksum |= c; \
+ while (++j < CS_BYTES) { \
+ (checksum) <<= 8; \
+ if (c) { \
+ c = (CS_TYPE)*++(k); \
+ checksum |= c; \
+ } \
} \
+ if (c) ++(k); \
checksum &= CASE_MASK; \
}
@@ -141,7 +141,6 @@
apreq_value_merge_t *merge;
int root[TABLE_HASH_SIZE];
- unsigned char flags;
};
@@ -157,7 +156,7 @@
/* NEVER KILL AN ENTRY THAT'S STILL WITHIN THE FOREST */
#define IN_FOREST(t,idx) ( !DEAD(idx) && ( (idx)[o].tree[UP] >= 0 || \
- (idx) == t->root[TABLE_HASH((idx)[o].checksum>>24)] ) )
+ (idx) == t->root[TABLE_HASH((idx)[o].checksum>>OFFSET)] )
)
/* MUST ensure n's parent exists (>=0) before using LR(n) */
#define LR(n) ( ( (n)[o].tree[UP][o].tree[LEFT] == (n) ) ? LEFT : RIGHT )
@@ -165,6 +164,7 @@
#define PROMOTE(r,p) do rotate(o,r,o[p].tree[UP],!LR(p)); \
while (o[p].tree[UP] >= 0)
+
/********************* (internal) tree operations ********************
*
* good general references for binary tree algorithms:
@@ -183,11 +183,9 @@
* 1 2 2 direction
*
*/
-
-static APR_INLINE void rotate(apreq_table_entry_t *o,
- int *root,
- const int pivot,
- const int direction)
+APR_INLINE
+static void rotate(apreq_table_entry_t *const o, int *root,
+ const int pivot, const int direction)
{
const int child = pivot[o].tree[!direction];
const int parent = pivot[o].tree[UP];
@@ -217,20 +215,19 @@
* were it added to the tree.
*
*/
-static APR_INLINE int search(apreq_table_entry_t *o,
- int *elt,
- const char *key)
-{
- int idx = *elt;
- apr_uint32_t checksum;
- if ( idx < 0)
- return 0;
+APR_INLINE
+static int search(const apreq_table_entry_t *const o,int *elt,
+ const char *key)
+{
+ register int idx = *elt;
+ register CS_TYPE csum;
- COMPUTE_KEY_CHECKSUM(key, checksum);
+ COMPUTE_KEY_CHECKSUM(key, csum);
while (1) {
- int direction = (checksum == idx[o].checksum) ?
- strcasecmp(key,idx[o].key) : checksum - idx[o].checksum;
+ const int direction = (csum > idx[o].checksum) ? 1 :
+ (csum < idx[o].checksum) ? -1 :
+ strcasecmp(key,idx[o].key);
if (direction < 0 && idx[o].tree[LEFT] >= 0)
idx = idx[o].tree[LEFT];
@@ -248,16 +245,15 @@
/* returns the index of the first similarly-named elt,
* and -1 otherwise (the elt is new).
*/
-static int insert(apreq_table_entry_t *o, int *root, int x,
- apreq_table_entry_t *elt,
- unsigned flags )
+static int insert(apreq_table_entry_t *const o, int *root, int x,
+ apreq_table_entry_t *elt)
{
- int idx = elt - o;
- int s;
+ const int idx = elt - o;
+ int s = 0;
#define REBALANCE do { \
int parent = x[o].tree[UP]; \
- x[o].color == RED; \
+ x[o].color = RED; \
if (parent >= 0 && parent[o].color == RED) { \
int parent_direction = LR(parent); \
int grandparent = parent[o].tree[UP]; \
@@ -271,19 +267,23 @@
} (*root)[o].color = BLACK; } while (0)
- if (flags & TF_BALANCE && *root != -1) {
+ if (x >= 0) {
/*
* M.A. Weiss' single-pass insertion algorithm for red-black trees
* corrects potential red-red violations prior to insertion:
* http://www.cs.uiowa.edu/~hzhang/c44/lec14.PDF
*/
+ const CS_TYPE csum = elt->checksum;
+ const char *const key = elt->key;
+
while (1) {
int left = x[o].tree[LEFT];
int right = x[o].tree[RIGHT];
- s = (elt->checksum == x[o].checksum) ?
- strcasecmp(elt->key,x[o].key) : elt->checksum -
x[o].checksum;
+ s = (csum > x[o].checksum) ? 1 :
+ (csum < x[o].checksum) ? -1 :
+ strcasecmp(key,x[o].key);
if (s < 0 && left >= 0) {
if (left[o].color == RED && right >= 0
@@ -307,8 +307,6 @@
break;
}
}
- else
- s = search(o, &x, elt->val->name);
if (s == 0) { /* found */
int parent = x;
@@ -341,17 +339,14 @@
elt->tree[RIGHT] = -1;
elt->tree[LEFT] = -1;
- if (flags & TF_BALANCE) {
- elt->color = RED;
- x = idx;
- REBALANCE;
- }
+ x = idx;
+ REBALANCE;
+
#undef REBALANCE
return -1;
}
-static void delete(apreq_table_entry_t *o,
- int *root, const int idx, unsigned flags)
+static void delete(apreq_table_entry_t *const o, int *root, const int idx)
{
int x;
int parent = idx[o].tree[UP];
@@ -370,7 +365,7 @@
else
x = parent;
- if (flags & TF_BALANCE == 0 || idx[o].color == RED)
+ if (idx[o].color == RED)
return;
}
else {
@@ -406,12 +401,10 @@
else
*root = y;
- if (flags & TF_BALANCE == 0 || y[o].color == RED) {
- y[o].color = idx[o].color;
- return;
- }
- else
- y[o].color = idx[o].color;
+ if (y[o].color == RED)
+ x = *root;
+
+ y[o].color = idx[o].color;
}
@@ -426,7 +419,7 @@
while (x != *root && x[o].color == BLACK) {
/* x has a parent & sibling */
int parent = x[o].tree[UP];
- register const int direction = LR(x);
+ const int direction = LR(x);
int sibling = parent[o].tree[!direction];
if (sibling[o].color == RED) {
@@ -490,7 +483,7 @@
a[o].tree[UP] = -1;
}
- if (insert(o,&a,a,b+o,0) < 0) /* b is a new element for a's tree */
+ if (insert(o,&a,a,b+o) < 0) /* b is a new element for a's tree */
rv = b;
if (b[o].tree[UP] >= 0)
@@ -567,7 +560,6 @@
t->merge = apreq_merge_values;
t->copy = apreq_copy_value;
- t->flags = 0;
t->ghosts = 0;
return t;
}
@@ -585,7 +577,6 @@
memcpy(new->root, t->root, TABLE_HASH_SIZE * sizeof(int));
new->merge = t->merge;
new->copy = t->copy;
- new->flags = t->flags;
return new;
}
@@ -608,15 +599,13 @@
}
APREQ_DECLARE(apreq_table_t *)apreq_table_import(apr_pool_t *p,
- const apr_table_t *s,
- const unsigned f)
+ const apr_table_t *s)
{
apreq_table_t *t = apreq_table_make(p,APREQ_NELTS);
const apr_array_header_t *a = apr_table_elts(s);
const apr_table_entry_t *e = (const apr_table_entry_t *)a->elts;
const apr_table_entry_t *end = e + a->nelts;
- t->flags = f;
for ( ; e < end; ++e) {
apreq_value_t *v = apreq_make_value(p, e->key, strlen(e->key),
@@ -676,29 +665,6 @@
}
-APREQ_DECLARE(void) apreq_table_balance(apreq_table_t *t, const int on)
-{
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
- if (on) {
- int idx;
- if (t->flags & TF_BALANCE)
- return;
-
- memset(t->root,-1,TABLE_HASH_SIZE * sizeof(int));
- for (idx = 0; idx < t->a.nelts; ++idx)
- if (!DEAD(idx))
- insert(o, &t->root[TABLE_HASH(idx[o].checksum>>24)],
- t->root[TABLE_HASH(idx[o].checksum>>24)], idx+o,
- TF_BALANCE);
-
- t->flags |= TF_BALANCE;
- }
- else {
- t->flags &= ~TF_BALANCE;
- }
-}
-
-
APREQ_DECLARE(apr_status_t) apreq_table_normalize(apreq_table_t *t)
{
apr_status_t status = APR_SUCCESS;
@@ -818,29 +784,12 @@
const char *key)
{
int idx = t->root[TABLE_HASH(*key)];
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
+ const apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
if ( idx < 0 || search(o,&idx,key) )
return NULL;
- return v2c(idx[o].val);
-}
-
-APREQ_DECLARE(const char *) apreq_table_cache(apreq_table_t *t,
- const char *key)
-{
- int *root = &t->root[TABLE_HASH(*key)];
- int idx = *root;
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
-
- if ( idx < 0 || search(o,&idx,key) )
- return NULL;
-
- if (idx != *root) {
- t->flags &= ~TF_BALANCE;
- PROMOTE(root,idx);
- }
- return v2c(idx[o].val);
+ return idx[o].val->data;
}
@@ -860,48 +809,20 @@
}
-
-APREQ_DECLARE(apr_status_t) apreq_table_values(const apreq_table_t *t,
- const char *key,
- apr_array_header_t *values)
-{
- int idx;
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
- if (t->a.nelts == t->ghosts)
- return APR_NOTFOUND;
-
- if (key == NULL) { /* fetch all values */
- for (idx = 0; idx < t->a.nelts; ++idx)
- if (IN_FOREST(t,idx))
- *(const apreq_value_t **)apr_array_push(values) = idx[o].val;
- }
- else {
- idx = t->root[TABLE_HASH(*key)];
- if ( idx>=0 && search(o,&idx,key) == 0 )
- for ( ; idx>=0; idx = idx[o].tree[NEXT] )
- *(const apreq_value_t **)apr_array_push(values) = idx[o].val;
- else
- return APR_NOTFOUND;
- }
-
- return APR_SUCCESS;
-}
-
-
APREQ_DECLARE(void) apreq_table_set(apreq_table_t *t,
const apreq_value_t *val)
{
const char *key = val->name;
int idx;
apreq_table_entry_t *e = table_push(t);
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
+ apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
e->key = key;
e->val = val;
e->tree[NEXT] = -1;
COMPUTE_KEY_CHECKSUM(e->key,e->checksum);
idx = insert(o,&t->root[TABLE_HASH(*key)],
- t->root[TABLE_HASH(*key)] ,e,t->flags);
+ t->root[TABLE_HASH(*key)] ,e);
if (idx >= 0) {
int n;
@@ -922,11 +843,11 @@
APREQ_DECLARE(void) apreq_table_unset(apreq_table_t *t, const char *key)
{
int idx = t->root[TABLE_HASH(*key)];
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
+ apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
if (idx >= 0 && search(o,&idx,key) == 0) {
int n;
- delete(o,&t->root[TABLE_HASH(*key)],idx, t->flags);
+ delete(o,&t->root[TABLE_HASH(*key)],idx);
for ( n=idx; n>=0; n=n[o].tree[NEXT] )
KILL(t,n);
}
@@ -939,13 +860,13 @@
const char *key = val->name;
int idx = t->root[TABLE_HASH(*key)];
apreq_table_entry_t *e = table_push(t);
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
+ apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
e->key = key;
e->val = val;
e->tree[NEXT] = -1;
COMPUTE_KEY_CHECKSUM(key,e->checksum);
- idx = insert(o,&t->root[TABLE_HASH(*key)],idx,e,t->flags);
+ idx = insert(o,&t->root[TABLE_HASH(*key)],idx,e);
if (idx >= 0) {
int n;
@@ -988,32 +909,16 @@
APREQ_DECLARE(apr_status_t) apreq_table_add(apreq_table_t *t,
const apreq_value_t *val)
{
- if (val == NULL || val->name == NULL)
- return APR_EGENERAL;
-
- switch (val->status) {
- case APR_SUCCESS:
- case APR_EINPROGRESS:
- case APR_INCOMPLETE:
- {
- const char *key = val->name;
- apreq_table_entry_t *elt = table_push(t);
- int *root = &t->root[TABLE_HASH(*key)];
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
-
- elt->key = key;
- elt->val = val;
- elt->tree[NEXT] = -1;
- COMPUTE_KEY_CHECKSUM(elt->key,elt->checksum);
- insert(o, root, *root, elt, t->flags);
- return APR_SUCCESS;
- }
-
- default:
- return val->status;
- }
+ const char *key = val->name;
+ apreq_table_entry_t *elt = table_push(t);
+ int *root = &t->root[TABLE_HASH(*key)];
+ apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
- /* NOT REACHED */
+ elt->key = key;
+ elt->val = val;
+ elt->tree[NEXT] = -1;
+ COMPUTE_KEY_CHECKSUM(elt->key,elt->checksum);
+ insert(o, root, *root, elt);
return APR_SUCCESS;
}
@@ -1029,9 +934,10 @@
int idx;
apreq_table_entry_t *o;
if (t->ghosts == n) {
- t->a.nelts == 0;
+ t->a.nelts = 0;
t->ghosts = s->ghosts;
apr_array_cat(&t->a,&s->a);
+ memcpy(t->root, s->root, TABLE_HASH_SIZE * sizeof(int));
return;
}
@@ -1039,35 +945,36 @@
o = (apreq_table_entry_t *)t->a.elts;
t->ghosts += s->ghosts;
- if (t->flags & TF_BALANCE) {
- for (idx = n; idx < t->a.nelts; ++idx) {
- const unsigned char hash = TABLE_HASH(idx[o].checksum>>24);
-
- if (DEAD(idx))
- continue;
-
- if (idx[o].tree[NEXT] >= 0)
- idx[o].tree[NEXT] += n;
-
- if (t->root[hash] < 0) {
- if (idx[o].tree[LEFT] >= 0)
- idx[o].tree[LEFT] += n;
- if (idx[o].tree[RIGHT] >= 0)
- idx[o].tree[RIGHT] += n;
- if (idx[o].tree[UP] >= 0)
- idx[o].tree[UP] += n;
+ for (idx = n; idx < t->a.nelts; ++idx) {
+ const unsigned char hash = TABLE_HASH(idx[o].checksum>>OFFSET);
- t->root[hash] = idx;
- }
- else if ( idx[o].tree[UP] >= 0 || s->root[hash] == idx-n )
- insert(o, &t->root[hash], t->root[hash], idx+o, TF_BALANCE);
+ if (DEAD(idx))
+ continue;
+
+ if (idx[o].tree[NEXT] >= 0)
+ idx[o].tree[NEXT] += n;
+
+ if (t->root[hash] < 0) {
+ if (idx[o].tree[LEFT] >= 0)
+ idx[o].tree[LEFT] += n;
+ if (idx[o].tree[RIGHT] >= 0)
+ idx[o].tree[RIGHT] += n;
+ if (idx[o].tree[UP] >= 0)
+ idx[o].tree[UP] += n;
+
+ t->root[hash] = idx;
}
+ else if ( idx[o].tree[UP] >= 0 || s->root[hash] == idx-n )
+ insert(o, &t->root[hash], t->root[hash], idx+o);
}
+}
+/*
else {
for (idx = 0; idx < TABLE_HASH_SIZE; ++idx)
t->root[idx] = combine(o,t->root[idx],s->root[idx],n);
}
}
+*/
APREQ_DECLARE(apreq_table_t *) apreq_table_overlay(apr_pool_t *p,
const apreq_table_t *overlay,
@@ -1079,7 +986,6 @@
t->a.elt_size = sizeof(apreq_table_entry_t);
t->copy = overlay->copy;
t->merge = overlay->merge;
- t->flags = overlay->flags;
t->ghosts = overlay->ghosts;
memcpy(t->root, overlay->root, TABLE_HASH_SIZE * sizeof(int));
@@ -1247,7 +1153,7 @@
va_list vp)
{
char *argp;
- apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
+ const apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
int vdorv = 1;
argp = va_arg(vp, char *);
@@ -1255,9 +1161,9 @@
int rv = 1, idx;
if (argp) { /* Scan for entries that match the next key */
idx = t->root[TABLE_HASH(*argp)];
- if ( search(o,&idx,argp) == 0 )
+ if ( idx >= 0 && search(o,&idx,argp) == 0 )
while (idx >= 0) {
- rv = (*comp) (rec, idx[o].val->name, v2c(idx[o].val));
+ rv = (*comp) (rec, idx[o].key, idx[o].val->data);
idx = idx[o].tree[NEXT];
}
}
@@ -1265,7 +1171,7 @@
for (idx = 0; rv && (idx < t->a.nelts); ++idx)
/* if (idx[o].key) */
if (! DEAD(idx) )
- rv = (*comp) (rec, idx[o].val->name, v2c(idx[o].val));
+ rv = (*comp) (rec, idx[o].key, idx[o].val->data);
}
if (rv == 0) {
vdorv = 0;
1.16 +2 -45 httpd-apreq-2/src/apreq_tables.h
Index: apreq_tables.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- apreq_tables.h 29 Apr 2003 03:35:55 -0000 1.15
+++ apreq_tables.h 3 May 2003 05:22:33 -0000 1.16
@@ -124,11 +124,9 @@
* Create an APREQ Table from an APR Table.
* @param p The pool to allocate the APREQ table from
* @param t The APR table to copy
- * @param f Flags for the APREQ table to use during construction.
*/
APREQ_DECLARE(apreq_table_t *)apreq_table_import(apr_pool_t *p,
- const apr_table_t *t,
- const unsigned f);
+ const apr_table_t *t);
/**
* Delete all of the elements from a table
@@ -145,6 +143,7 @@
APREQ_DECLARE(int) apreq_table_nelts(const apreq_table_t *t);
#define apreq_table_is_empty(t) ( apreq_table_nelts(t) == 0 )
+
/**
* Get/set method for the table's value copier.
* @param t Table.
@@ -168,21 +167,6 @@
apreq_value_merge_t *m);
/**
- * Change the behavior of the table's internal search trees.
- * @param t Table.
- * @param on Activate/deactivate additional balancing algorithms.
- * @remark By default, APREQ Tables use binary search trees to
- * improve lookup performance. This function can instruct
- * the table to maintain balance within those trees.
- * In typical ( < 100 table entries ) situations, the
- * additional overhead needed for maintaining tree-balance
- * will cause performance to worsen, not improve.
- *
- * Handle with care.
- */
-APREQ_DECLARE(void) apreq_table_balance(apreq_table_t *t, const int on);
-
-/**
* Attempt to merge multivalued entries together, eliminating
* redunandant entries with t->merge. See apreq_table_merger
* for additional details.
@@ -224,21 +208,6 @@
const char *key);
/**
- * Get the value associated with a given key from the table,
- * and cache the entry at the root of the tree it was found in.
- * @param t The table to search for the key
- * @param key The key to search for
- * @return The data associated with the key, guaranteed to
- * point at the "data" attribute of an apreq_value_t struct.
- *
- * @remark Caching is incompatible with tree-balance, so this
- * function may deactivate the tree-balancing algorithm if
- * necessary.
- */
-APREQ_DECLARE(const char *) apreq_table_cache(apreq_table_t *t,
- const char *key);
-
-/**
* Return the keys (i.e. value names) in an (char *) array,
* preserving their original order.
* @param t Table.
@@ -248,18 +217,6 @@
APREQ_DECLARE(apr_status_t) apreq_table_keys(const apreq_table_t *t,
apr_array_header_t *keys);
-/**
- * Return the (unique) values in an (apreq_value_t *) array,
- * preserving their original order.
- * @param t Table.
- * @param values array used to sore the result..
- * @remark With key == NULL, all table values are added. However,
- * only the first value of a multivalued entry is used.
- */
-
-APREQ_DECLARE(apr_status_t) apreq_table_values(const apreq_table_t *t,
- const char *key,
- apr_array_header_t *values);
/**
* Add an apreq_value_t to the table. If another value already exists
* with the same name, this will replace the old value.
1.7 +1 -1 httpd-apreq-2/t/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /home/cvs/httpd-apreq-2/t/Makefile.am,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Makefile.am 24 Apr 2003 20:17:17 -0000 1.6
+++ Makefile.am 3 May 2003 05:22:33 -0000 1.7
@@ -2,7 +2,7 @@
LIBS = -L../src
noinst_LIBRARIES = libapreq_tests.a
-libapreq_tests_a_SOURCES = CuTest.c env.c tables.c cookie.c params.c
parsers.c
+libapreq_tests_a_SOURCES = CuTest.c env.c tables.c cookie.c params.c
parsers.c performance.c
libapreq_tests_a_LIBADD = ../src/libapreq.la
check_PROGRAMS = testall
1.3 +2 -3 httpd-apreq-2/t/cookie.c
Index: cookie.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/t/cookie.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- cookie.c 21 Apr 2003 19:40:11 -0000 1.2
+++ cookie.c 3 May 2003 05:22:33 -0000 1.3
@@ -95,7 +95,6 @@
{
apreq_cookie_t *c;
apreq_cookie_version_t version = NETSCAPE;
- char *expires = apreq_expires(p,"+1y", NSCOOKIE);
c = apreq_cookie(j,"foo");
CuAssertStrEquals(tc,"bar",apreq_cookie_value(c));
@@ -109,11 +108,10 @@
c->path = apr_pstrdup(p, "/quux");
CuAssertStrEquals(tc, "foo=bar; path=/quux; domain=example.com",
apreq_cookie_as_string(p,c));
-
apreq_cookie_expires(p, c, "+1y");
CuAssertStrEquals(tc,apr_pstrcat(p,
"foo=bar; path=/quux; domain=example.com;
expires=",
- expires, NULL), apreq_cookie_as_string(p,c));
+ apreq_expires(p,"+1y",NSCOOKIE), NULL),
apreq_cookie_as_string(p,c));
}
@@ -153,6 +151,7 @@
SUITE_ADD_TEST(suite, jar_table_get);
SUITE_ADD_TEST(suite, netscape_cookie);
SUITE_ADD_TEST(suite, rfc_cookie);
+
return suite;
}
1.9 +23 -27 httpd-apreq-2/t/tables.c
Index: tables.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/t/tables.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- tables.c 25 Apr 2003 18:11:15 -0000 1.8
+++ tables.c 3 May 2003 05:22:33 -0000 1.9
@@ -75,7 +75,6 @@
{
t1 = apreq_make_table(p, 5);
CuAssertPtrNotNull(tc, t1);
- apreq_table_balance(t1,1);
}
static void table_get(CuTest *tc)
@@ -310,6 +309,7 @@
{
const char *k;
apr_array_header_t *a = apr_array_make(p,1, sizeof k);
+
apr_status_t s = apreq_table_keys(t1,a);
CuAssertIntEquals(tc, APR_SUCCESS, s);
CuAssertIntEquals(tc, 7, a->nelts);
@@ -329,39 +329,35 @@
CuAssertStrEquals(tc, "f", k);
}
+static int push_value(void *d, const char *key, const char *val)
+{
+ apr_array_header_t *a = d;
+ *(const char **)apr_array_push(a) = val;
+ return 1;
+}
+
static void table_values(CuTest *tc)
{
- const apreq_value_t *v;
+ const char *v;
apr_array_header_t *a = apr_array_make(p,1,sizeof v);
- apr_status_t s = apreq_table_values(t1,"a",a);
- CuAssertIntEquals(tc, APR_SUCCESS, s);
+ apreq_table_do(push_value, a, t1, "a", NULL);
+
CuAssertIntEquals(tc, 2, a->nelts);
- v = ((const apreq_value_t **)a->elts)[0];
- CuAssertStrEquals(tc, "a", v->name);
- CuAssertStrEquals(tc, "0", v->data);
- v = ((const apreq_value_t **)a->elts)[1];
- CuAssertStrEquals(tc, "a", v->name);
- CuAssertStrEquals(tc, "1", v->data);
+ v = ((const char **)a->elts)[0];
+ CuAssertStrEquals(tc, "0", v);
+ v = ((const char **)a->elts)[1];
+ CuAssertStrEquals(tc, "1", v);
a->nelts = 0;
- s = apreq_table_values(t1,"b",a);
- CuAssertIntEquals(tc, APR_SUCCESS, s);
- CuAssertIntEquals(tc, 3, a->nelts);
- v = ((const apreq_value_t **)a->elts)[0];
- CuAssertStrEquals(tc, "b", v->name);
- CuAssertStrEquals(tc, "2", v->data);
- v = ((const apreq_value_t **)a->elts)[1];
- CuAssertStrEquals(tc, "b", v->name);
- CuAssertStrEquals(tc, "2.0", v->data);
- v = ((const apreq_value_t **)a->elts)[2];
- CuAssertStrEquals(tc, "b", v->name);
- CuAssertStrEquals(tc, "2.", v->data);
+ apreq_table_do(push_value, a, t1, "b", NULL);
- a->nelts = 0;
- s = apreq_table_values(t1,NULL,a);
- CuAssertIntEquals(tc, APR_SUCCESS, s);
- CuAssertIntEquals(tc, 7, a->nelts);
-
+ CuAssertIntEquals(tc, 3, a->nelts);
+ v = ((const char **)a->elts)[0];
+ CuAssertStrEquals(tc, "2", v);
+ v = ((const char **)a->elts)[1];
+ CuAssertStrEquals(tc, "2.0", v);
+ v = ((const char **)a->elts)[2];
+ CuAssertStrEquals(tc, "2.", v);
}
1.5 +1 -1 httpd-apreq-2/t/test_apreq.h
Index: test_apreq.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/t/test_apreq.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- test_apreq.h 24 Apr 2003 20:17:17 -0000 1.4
+++ test_apreq.h 3 May 2003 05:22:33 -0000 1.5
@@ -71,7 +71,7 @@
CuSuite *testenv(void);
CuSuite *testparam(void);
CuSuite *testparser(void);
-
+CuSuite *testperformance(void);
/* Assert that RV is an APR_SUCCESS value; else fail giving strerror
* for RV and CONTEXT message. */
void apr_assert_success(CuTest* tc, const char *context, apr_status_t rv);
1.7 +1 -0 httpd-apreq-2/t/testall.c
Index: testall.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/t/testall.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- testall.c 24 Apr 2003 20:17:17 -0000 1.6
+++ testall.c 3 May 2003 05:22:33 -0000 1.7
@@ -82,6 +82,7 @@
{"cookies", testcookie},
{"params", testparam},
{"parsers", testparser},
+ {"performance", testperformance},
{"LastTest", NULL}
};
1.1 httpd-apreq-2/t/performance.c
Index: performance.c
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "apr_time.h"
#include "apr_strings.h"
#include "apreq_env.h"
#include "test_apreq.h"
#include "apreq.h"
#include "apreq_tables.h"
#include "apr_hash.h"
#if APR_HAVE_STDIO_H
#include <stdio.h>
#endif
#if APR_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if APR_HAVE_STRING_H
#include <string.h>
#endif
static apreq_table_t *t = NULL;
static apreq_table_t *s = NULL;
static apreq_table_t *h = NULL;
#define LOOP 10000
#define FAIL(MSG) \
CuFail(tc, apr_psprintf(p, MSG ": APR = %.3f vs APREQ = %.3f
(microseconds)", \
(double)apr_delta / LOOP, (double)apreq_delta /
LOOP))
#define TEST_DELTAS(winner,loser,MSG) if (winner##_delta > loser##_delta)
FAIL(MSG)
#define RUN_GET(k,v) do {apr_time_t apr_delta,apreq_delta;const char *val; \
int i; apreq_delta = apr_time_now(); for(i=0;i<LOOP;++i) val = \
apreq_table_get(t,k); apreq_delta = apr_time_now() - apreq_delta; \
if (v) { CuAssertPtrNotNull(tc,val);CuAssertStrEquals(tc,v,val);} \
else CuAssertPtrEquals(tc,NULL,val); \
apr_delta = apr_time_now(); for(i=0;i<LOOP;++i) val = apr_table_get(s,k); \
apr_delta = apr_time_now() - apr_delta; \
if (v) {CuAssertPtrNotNull(tc,val); CuAssertStrEquals(tc,v,val);} \
else CuAssertPtrEquals(tc,NULL,val);\
TEST_DELTAS(apreq,apr,"apr_table_get(" k ") wins"); apr_delta =
apr_time_now(); \
/* for(i=0;i<LOOP;++i) val = apr_hash_get(h,k,APR_HASH_KEY_STRING);\
apr_delta = apr_time_now() - apr_delta; \
if (v) {CuAssertPtrNotNull(tc,val);CuAssertStrEquals(tc,v,val);} \
else CuAssertPtrEquals(tc,NULL,val); \
TEST_DELTAS(apreq,apr,"APR hash_get(" k ") wins"); \
*/} while (0)
#define V(k,v) apreq_make_value(p,k,strlen(k),v,strlen(v))
#define VV(k) { #k, 0, 1, 0 }
static char *headers[12] = {"Host", "User-Agent", "Accept",
"Accept-Language", "Accept-Encoding",
"Accept-Charset", "Keep-Alive",
"Connection", "Referer", "Cookie",
"Content-Type", "Content-Length"};
static apreq_table_t *init_apreq(int N)
{
apreq_table_t *t = apreq_table_make(p,N);
int j;
static apreq_value_t v[] = { VV(Host), VV(User-Agent), VV(Accept),
VV(Accept-Language), VV(Accept-Encoding),
VV(Accept-Charset), VV(Keep-Alive),
VV(Connection), VV(Referer), VV(Cookie),
VV(Content-Type), VV(Content-Length) };
for (j = 0; j < 12; ++j)
apreq_table_add(t,v + j);
return t;
}
static apr_table_t *init_apr(int N)
{
apr_table_t *t = apr_table_make(p,N);
int j;
for (j=0; j < 12; ++j)
apr_table_addn(t, headers[j], "");
return t;
}
static apr_hash_t *init_hash(void)
{
apr_hash_t *h = apr_hash_make(p);
int j;
for (j = 0; j < 12; ++j) {
const char *k = headers[j];
int klen = strlen(k);
const char *v = apr_hash_get(h, k, klen);
if (v == NULL)
apr_hash_set(h, k, klen, "");
else
apr_hash_set(h, k, klen, apr_pstrcat(p,v,", ", k, NULL));
}
return h;
}
/* measures httpd server's request header initialization time */
static void perf_init(CuTest *tc)
{
apr_time_t apreq_delta,apr_delta;
int i;
apreq_delta = apr_time_now();
for (i=0; i<LOOP;++i) {
apreq_table_t *t = init_apreq(APREQ_NELTS*2);
apreq_table_normalize(t);
}
apreq_delta = apr_time_now() - apreq_delta;
apr_delta = apr_time_now();
for (i=0; i<LOOP;++i) {
apr_table_t *t = apr_table_make(p,APREQ_NELTS*2);
apr_table_t *s = init_apr(APREQ_NELTS*2);
apr_table_overlap(t,s,APR_OVERLAP_TABLES_MERGE);
}
apr_delta = apr_time_now() - apr_delta;
TEST_DELTAS(apreq,apr,"apreq should win");
apr_delta = apr_time_now();
for (i=0; i<LOOP;++i) {
apr_hash_t *h = init_hash();
}
apr_delta = apr_time_now() - apr_delta;
TEST_DELTAS(apr,apreq,"apr_hash should win");
}
#define GET_AVG(N) \
apr_delta = apr_time_now(); \
for (j = 0; j < LOOP; ++j) { \
const char *val = apr_table_get(s, headers[j % N]); \
CuAssertPtrNotNull(tc, val); \
} \
apr_delta = apr_time_now() - apr_delta; \
apreq_delta = apr_time_now(); \
for (j = 0; j < LOOP; ++j) { \
const char *val = apreq_table_get(t, headers[j % N]); \
CuAssertPtrNotNull(tc, val); \
} \
apreq_delta = apr_time_now() - apreq_delta;
static void perf_get_avg(CuTest *tc)
{
apr_table_t *s = init_apr(APREQ_NELTS);
apreq_table_t *t = init_apreq(APREQ_NELTS);
apr_time_t apr_delta, apreq_delta;
int j;
GET_AVG (2); TEST_DELTAS(apr,apreq,"apr_tables should win (2)");
GET_AVG (4); TEST_DELTAS(apr,apreq,"apr_tables should win (4)");
GET_AVG (6); TEST_DELTAS(apreq,apr,"apreq should win (6)");
GET_AVG (8); TEST_DELTAS(apreq,apr,"apreq should win (8)");
GET_AVG(10); TEST_DELTAS(apreq,apr,"apreq should win (10)");
GET_AVG(12); TEST_DELTAS(apreq,apr,"apreq should win (12)");
}
/*
* nontrivial trees
* ------------------
*
* (4) Accept-Encoding (7) Connection
* / \ / \
* (2) Accept Accept-Language (3) (9) Cookie Content-Type (10)
* \ /
* (5) Accept-Charset Content-Length (11)
*/
static void perf_get(CuTest *tc)
{
apr_hash_t *h = init_hash();
apr_table_t *s = init_apr(APREQ_NELTS);
apreq_table_t *t = init_apreq(APREQ_NELTS);
apr_time_t apr_delta, apreq_delta;
int j;
/* expected apr winners: "Accept", "Connection" "Cookie" */
/* expected apreq winners: */
RUN_GET("Accept-Encoding","");
RUN_GET("Accept-Charset","");
RUN_GET("Accept-Language","");
RUN_GET("Content-Length","");
RUN_GET("Content-Type",""); /* apr wins by .05 microseconds now */
}
#ifdef footoo
static void table_set(CuTest *tc)
{
const char *val;
apreq_table_t *t = init_apreq(APREQ_NELTS);
apr_table_t *s = init_apr(APREQ_NELTS);
apreq_table_set(t1, V("setkey","bar"));
apreq_table_set(t1, V("setkey","2ndtry"));
val = apreq_table_get(t1,"setkey");
CuAssertStrEquals(tc,"2ndtry",val);
}
static void table_getnotthere(CuTest *tc)
{
const char *val;
val = apreq_table_get(t1, "keynotthere");
CuAssertPtrEquals(tc, NULL,val);
}
static void table_add(CuTest *tc)
{
const char *val;
apreq_table_add(t1, V("add", "bar"));
apreq_table_add(t1, V("add", "foo"));
val = apreq_table_get(t1, "add");
CuAssertStrEquals(tc, "bar", val);
apreq_table_add(t1, V("f", "top"));
apreq_table_add(t1, V("fo", "child"));
apreq_table_add(t1, V("fro", "child-right"));
apreq_table_add(t1, V("foo", "bar"));
/*
* f(5) black fo(6) black
* fo(6) red => f(5)red fro(7)red
* fro(7) red
*
*/
apreq_table_add(t1, V("flo", "child-left"));
apreq_table_add(t1, V("flr", "child-left-right"));
apreq_table_add(t1, V("frr", "child-right-right"));
apreq_table_add(t1, V("frl", "child-right-left"));
apreq_table_add(t1, V("flr", "child-left-right"));
apreq_table_add(t1, V("fll", "child-left-left"));
apreq_table_add(t1, V("foot", "bart"));
apreq_table_add(t1, V("foon", "barn"));
apreq_table_add(t1, V("foot", "bart"));
apreq_table_add(t1, V("foop", "barp"));
apreq_table_add(t1, V("food", "bard"));
apreq_table_add(t1, V("foof", "barf"));
apreq_table_add(t1, V("fooz", "barz"));
apreq_table_add(t1, V("fooq", "barq"));
apreq_table_add(t1, V("foot", "bart"));
apreq_table_add(t1, V("fooj", "barj"));
apreq_table_add(t1, V("fook", "bark"));
apreq_table_add(t1, V("fool", "barl"));
apreq_table_add(t1, V("foor", "barr"));
apreq_table_add(t1, V("foos", "bars"));
apreq_table_add(t1, V("foot", "bart"));
apreq_table_add(t1, V("foon", "barn"));
apreq_table_add(t1, V("foot", "bart"));
apreq_table_add(t1, V("foop", "barp"));
apreq_table_add(t1, V("food", "bard"));
apreq_table_add(t1, V("foof", "barf"));
apreq_table_add(t1, V("fooz", "barz"));
apreq_table_add(t1, V("fooq", "barq"));
apreq_table_add(t1, V("foot", "bart"));
apreq_table_add(t1, V("fooj", "barj"));
apreq_table_add(t1, V("fook", "bark"));
apreq_table_add(t1, V("fool", "barl"));
apreq_table_add(t1, V("foor", "barr"));
apreq_table_add(t1, V("foos", "bars"));
apreq_table_add(t1, V("quux", "quux"));
apreq_table_add(t1, V("quuxa", "quuxa"));
apreq_table_add(t1, V("quuxz", "quuxz"));
apreq_table_add(t1, V("quuxb", "quuxb"));
apreq_table_add(t1, V("quuxg", "quuxg"));
apreq_table_add(t1, V("quuxw", "quuxw"));
apreq_table_add(t1, V("quuxr", "quuxr"));
apreq_table_add(t1, V("alpha", "omega"));
val = apreq_table_get(t1, "foo");
CuAssertStrEquals(tc, "bar", val);
val = apreq_table_get(t1, "quuxb");
CuAssertStrEquals(tc, "quuxb", val);
val = apreq_table_get(t1,"flo");
CuAssertStrEquals(tc, "child-left", val);
}
static void table_unset(CuTest *tc) {
const char *val;
apreq_table_unset(t1, "flo");
val = apreq_table_get(t1, "flo");
CuAssertPtrEquals(tc, NULL, val);
val = apreq_table_get(t1, "fro");
CuAssertStrEquals(tc, "child-right", val);
val = apreq_table_get(t1, "fll");
CuAssertStrEquals(tc, "child-left-left", val);
val = apreq_table_get(t1, "frl");
CuAssertStrEquals(tc, "child-right-left", val);
}
static void table_perf(CuTest *tc)
{
CuAssertStrEquals(tc, "quuxb", apreq_table_get(t1,"quuxb"));
RUN_GET("alpha", "omega", "APR wins worst-case scenario");
RUN_GET("quuxb", "quuxb", "APR wins multi-key case 1");
RUN_GET("quuxw", "quuxw", "APR wins multi-key case 2");
RUN_GET("foonot", NULL, "APR wins missing-key case");
}
static void table_perf2(CuTest *tc)
{
RUN_GET("fool", "barl", "APR wins multi-key case 3");
RUN_GET(APREQ_URL_ENCTYPE, "foo","APR wins triple-key case");
RUN_GET(APREQ_MFD_ENCTYPE, "bar","APR wins single-key case");
}
static void table_cache(CuTest *tc)
{
apr_table_t *t2 = apreq_table_export(p,t1);
apr_time_t start, apr_delta, apreq_delta;
const char *val;
int i;
start = apr_time_now();
for (i = 0; i < LOOP; ++i)
val = apr_table_get(t2, "foo");
apr_delta = apr_time_now() - start;
CuAssertStrEquals(tc, "bar", val);
start = apr_time_now();
for (i = 0; i < LOOP; ++i)
val = apreq_table_get(t1, "foo");
apreq_delta = apr_time_now() - start;
CuAssertStrEquals(tc, "bar", val);
// CuAssertTrue(tc, apreq_delta > apr_delta);
/* apr_tables should win (above), since foo is the first "f" item;
* but it should lose to apreq_tables when cacheing is enabled (below).
*/
CuAssertStrEquals(tc, "bar", apreq_table_cache(t1,"foo"));
start = apr_time_now();
for (i = 0; i < LOOP; ++i)
val = apreq_table_get(t1, "foo");
apreq_delta = apr_time_now() - start;
CuAssertStrEquals(tc, "bar", val);
TEST_DELTAS("APR beats apreq's cache");
}
static void table_nelts(CuTest *tc)
{
const char *val;
apreq_table_t *t = apreq_table_make(p, 1);
apreq_table_set(t, V("abc", "def"));
apreq_table_set(t, V("def", "abc"));
apreq_table_set(t, V("foo", "zzz"));
val = apreq_table_get(t, "foo");
CuAssertStrEquals(tc, val, "zzz");
val = apreq_table_get(t, "abc");
CuAssertStrEquals(tc, val, "def");
val = apreq_table_get(t, "def");
CuAssertStrEquals(tc, val, "abc");
CuAssertIntEquals(tc, 3, apreq_table_nelts(t));
}
static void table_clear(CuTest *tc)
{
apreq_table_clear(t1);
CuAssertIntEquals(tc, 0, apreq_table_nelts(t1));
}
static void table_overlap(CuTest *tc)
{
const char *val;
apreq_table_t *t2 = init_apreq(APREQ_NELTS);
apr_table_t *r1, *r2;
apr_status_t s;
apr_time_t start, apreq_delta, apr_delta;
t1 = apreq_table_make(p, APREQ_NELTS);
r1 = apreq_table_export(p,t1);
r2 = apreq_table_export(p,t2);
/* APR_OVERLAP_TABLES_SET had funky semantics, so we ignore it here */
start = apr_time_now();
s = apreq_table_overlap(t1, t2, APR_OVERLAP_TABLES_MERGE);
apreq_delta = apr_time_now() - start;
CuAssertIntEquals(tc, APR_SUCCESS, s);
CuAssertIntEquals(tc, 12, apreq_table_nelts(t1));
start = apr_time_now();
apr_table_overlap(r1, r2, APR_OVERLAP_TABLES_MERGE);
apr_delta = apr_time_now() - start;
CuAssertIntEquals(tc, 12, apr_table_elts(r1)->nelts);
if (apr_delta < apreq_delta)
CuFail(tc, apr_psprintf(p, "APR wins overlap contest #1: %"
APR_INT64_T_FMT
" < %" APR_INT64_T_FMT " (microseconds)",
apr_delta,apreq_delta));
t1 = apreq_table_make(p, 1);
t2 = apreq_table_make(p,1);
apreq_table_add(t1, V("a", "0"));
apreq_table_add(t1, V("g", "7"));
apreq_table_add(t2, V("a", "1"));
apreq_table_add(t2, V("b", "2"));
apreq_table_add(t2, V("c", "3"));
apreq_table_add(t2, V("b", "2.0"));
apreq_table_add(t2, V("d", "4"));
apreq_table_add(t2, V("e", "5"));
apreq_table_add(t2, V("b", "2."));
apreq_table_add(t2, V("f", "6"));
r1 = apreq_table_export(p,t1);
r2 = apreq_table_export(p,t2);
/* APR_OVERLAP_TABLES_SET had funky semantics, so we ignore it here */
val = apreq_table_get(t1, "a");
CuAssertStrEquals(tc, "0",val);
start = apr_time_now();
s = apreq_table_overlap(t1, t2, APR_OVERLAP_TABLES_MERGE);
apreq_delta = apr_time_now() - start;
CuAssertIntEquals(tc, APR_SUCCESS, s);
CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
start = apr_time_now();
apr_table_overlap(r1, r2, APR_OVERLAP_TABLES_MERGE);
apr_delta = apr_time_now() - start;
CuAssertIntEquals(tc, 7, apr_table_elts(r1)->nelts);
if (apr_delta < apreq_delta)
CuFail(tc, apr_psprintf(p, "APR wins overlap contest #2: %"
APR_INT64_T_FMT
" < %" APR_INT64_T_FMT " (microseconds)",
apr_delta,apreq_delta));
t2 = apreq_table_copy(p,t1);
CuAssertIntEquals(tc, 3, apreq_table_ghosts(t2));
CuAssertIntEquals(tc, 9, apreq_table_exorcise(t2));
CuAssertIntEquals(tc, 0, apreq_table_ghosts(t2));
CuAssertIntEquals(tc, 7, apreq_table_nelts(t2));
val = apreq_table_get(t2, "a");
CuAssertStrEquals(tc, "0, 1",val);
val = apreq_table_get(t2, "b");
CuAssertStrEquals(tc, "2, 2.0, 2.",val);
val = apreq_table_get(t2, "c");
CuAssertStrEquals(tc, "3",val);
val = apreq_table_get(t2, "d");
CuAssertStrEquals(tc, "4",val);
val = apreq_table_get(t2, "e");
CuAssertStrEquals(tc, "5",val);
val = apreq_table_get(t2, "f");
CuAssertStrEquals(tc, "6",val);
val = apreq_table_get(t2, "g");
CuAssertStrEquals(tc, "7",val);
}
#define APREQ_ELT(a,i) (*(apreq_value_t **)((a)->elts + (i) * (a)->elt_size))
static void table_elts(CuTest *tc)
{
const char *val;
const apreq_value_t *v;
const apr_array_header_t *a;
CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
CuAssertIntEquals(tc, 3, apreq_table_ghosts(t1));
a = apreq_table_elts(t1);
CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
CuAssertIntEquals(tc, 0, apreq_table_ghosts(t1));
v = APREQ_ELT(a,0);
CuAssertStrEquals(tc,"0, 1", v->data);
v = APREQ_ELT(a,1);
CuAssertStrEquals(tc,"7", v->data);
v = APREQ_ELT(a,2);
CuAssertStrEquals(tc,"2, 2.0, 2.", v->data);
v = APREQ_ELT(a,3);
CuAssertStrEquals(tc,"3", v->data);
v = APREQ_ELT(a,a->nelts-1);
CuAssertStrEquals(tc,"6", v->data);
v = APREQ_ELT(a,a->nelts-2);
CuAssertStrEquals(tc,"5", v->data);
v = APREQ_ELT(a,a->nelts-3);
CuAssertStrEquals(tc,"4", v->data);
}
static void table_overlay(CuTest *tc)
{
const char *val;
apreq_table_t *t2 = apreq_table_make(p, 1);
apr_status_t s;
t1 = apreq_table_make(p, 1);
apreq_table_add(t1, V("a", "0"));
apreq_table_add(t1, V("g", "7"));
apreq_table_add(t2, V("a", "1"));
apreq_table_add(t2, V("b", "2"));
apreq_table_add(t2, V("c", "3"));
apreq_table_add(t2, V("b", "2.0"));
apreq_table_add(t2, V("d", "4"));
apreq_table_add(t2, V("e", "5"));
apreq_table_add(t2, V("b", "2."));
apreq_table_add(t2, V("f", "6"));
t1 = apreq_table_overlay(p, t1, t2);
CuAssertIntEquals(tc, 10, apreq_table_nelts(t1));
val = apreq_table_get(t1, "a");
CuAssertStrEquals(tc, "0",val);
val = apreq_table_get(t1, "b");
CuAssertStrEquals(tc, "2",val);
val = apreq_table_get(t1, "c");
CuAssertStrEquals(tc, "3",val);
val = apreq_table_get(t1, "d");
CuAssertStrEquals(tc, "4",val);
val = apreq_table_get(t1, "e");
CuAssertStrEquals(tc, "5",val);
val = apreq_table_get(t1, "f");
CuAssertStrEquals(tc, "6",val);
val = apreq_table_get(t1, "g");
CuAssertStrEquals(tc, "7",val);
}
static void table_keys(CuTest *tc)
{
const char *k;
apr_array_header_t *a = apr_array_make(p,1, sizeof k);
apr_status_t s = apreq_table_keys(t1,a);
CuAssertIntEquals(tc, APR_SUCCESS, s);
CuAssertIntEquals(tc, 7, a->nelts);
k = ((const char **)a->elts)[0];
CuAssertStrEquals(tc, "a", k);
k = ((const char **)a->elts)[1];
CuAssertStrEquals(tc, "g", k);
k = ((const char **)a->elts)[2];
CuAssertStrEquals(tc, "b", k);
k = ((const char **)a->elts)[3];
CuAssertStrEquals(tc, "c", k);
k = ((const char **)a->elts)[4];
CuAssertStrEquals(tc, "d", k);
k = ((const char **)a->elts)[5];
CuAssertStrEquals(tc, "e", k);
k = ((const char **)a->elts)[6];
CuAssertStrEquals(tc, "f", k);
}
static void table_values(CuTest *tc)
{
const apreq_value_t *v;
apr_array_header_t *a = apr_array_make(p,1,sizeof v);
apr_status_t s = apreq_table_values(t1,"a",a);
CuAssertIntEquals(tc, APR_SUCCESS, s);
CuAssertIntEquals(tc, 2, a->nelts);
v = ((const apreq_value_t **)a->elts)[0];
CuAssertStrEquals(tc, "a", v->name);
CuAssertStrEquals(tc, "0", v->data);
v = ((const apreq_value_t **)a->elts)[1];
CuAssertStrEquals(tc, "a", v->name);
CuAssertStrEquals(tc, "1", v->data);
a->nelts = 0;
s = apreq_table_values(t1,"b",a);
CuAssertIntEquals(tc, APR_SUCCESS, s);
CuAssertIntEquals(tc, 3, a->nelts);
v = ((const apreq_value_t **)a->elts)[0];
CuAssertStrEquals(tc, "b", v->name);
CuAssertStrEquals(tc, "2", v->data);
v = ((const apreq_value_t **)a->elts)[1];
CuAssertStrEquals(tc, "b", v->name);
CuAssertStrEquals(tc, "2.0", v->data);
v = ((const apreq_value_t **)a->elts)[2];
CuAssertStrEquals(tc, "b", v->name);
CuAssertStrEquals(tc, "2.", v->data);
a->nelts = 0;
s = apreq_table_values(t1,NULL,a);
CuAssertIntEquals(tc, APR_SUCCESS, s);
CuAssertIntEquals(tc, 7, a->nelts);
}
#endif
CuSuite *testperformance(void)
{
CuSuite *suite = CuSuiteNew("Performance");
SUITE_ADD_TEST(suite, perf_init);
SUITE_ADD_TEST(suite, perf_get_avg);
SUITE_ADD_TEST(suite, perf_get);
/*
SUITE_ADD_TEST(suite, table_set);
SUITE_ADD_TEST(suite, table_getnotthere);
SUITE_ADD_TEST(suite, table_add);
SUITE_ADD_TEST(suite, table_unset);
SUITE_ADD_TEST(suite, table_perf);
SUITE_ADD_TEST(suite, table_perf2);
SUITE_ADD_TEST(suite, table_cache);
SUITE_ADD_TEST(suite, table_nelts);
SUITE_ADD_TEST(suite, table_clear);
SUITE_ADD_TEST(suite, table_overlap);
SUITE_ADD_TEST(suite, table_elts);
SUITE_ADD_TEST(suite, table_overlay);
SUITE_ADD_TEST(suite, table_keys);
SUITE_ADD_TEST(suite, table_values);
*/
return suite;
}